Hi All
Currently TASK_UNMAPPED_BASE in PPC is defined to:
#define TASK_UNMAPPED_BASE (TASK_SIZE / 8 *3) which is 0x30000000
in glibc ldso's JMP_SLOT you have:
{
Elf32_Sword delta = finaladdr - (Elf32_Word) reloc_addr;
if (delta << 6 >> 6 == delta)
*reloc_addr = OPCODE_B (delta);
else if (finaladdr <= 0x01fffffc || finaladdr >= 0xfe000000)
*reloc_addr = OPCODE_BA (finaladdr);
else
{
Elf32_Word *plt, *data_words;
Elf32_Word index, offset, num_plt_entries;
plt = (Elf32_Word *) D_PTR (map, l_info[DT_PLTGOT]);
offset = reloc_addr - plt;
if (offset < PLT_DOUBLE_SIZE*2 + PLT_INITIAL_ENTRY_WORDS)
{
index = (offset - PLT_INITIAL_ENTRY_WORDS)/2;
num_plt_entries = (map->l_info[DT_PLTRELSZ]->d_un.d_val
/ sizeof(Elf32_Rela));
data_words = plt + PLT_DATA_START_WORDS (num_plt_entries);
data_words[index] = finaladdr;
reloc_addr[0] = OPCODE_LI (11, index * 4);
reloc_addr[1] = OPCODE_B ((PLT_LONGBRANCH_ENTRY_WORDS
- (offset+1))
* 4);
MODIFIED_CODE_NOQUEUE (reloc_addr + 1);
}
else
{
reloc_addr[0] = OPCODE_LIS_HI (12, finaladdr);
reloc_addr[1] = OPCODE_ADDI (12, 12, finaladdr);
reloc_addr[2] = OPCODE_MTCTR (12);
reloc_addr[3] = OPCODE_BCTR ();
MODIFIED_CODE_NOQUEUE (reloc_addr + 3);
}
}
}
break;
The if (delta << 6 >> 6 == delta) is commonly false.
If finaladdr is <= 0x01fffffc then the relocation is much cheaper than the last else statement.
But since TASK_UNMAPPED_BASE is 0x30000000, finaladdr will never be <= 0x01fffffc unless
a shared library asks for a low address.
I changed TASK_UNMAPPED_BASE to well under 0x01fffffc and it worked as well.
My question: Why is TASK_UNMAPPED_BASE=0x30000000 and would changing it to something
less, say 0x00100000 be a problem?
Jocke
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
From: Franz Sirl <hidden> Date: 2004-02-03 15:22:28
At 14:05 03.02.2004, Joakim Tjernlund wrote:
Hi All
Currently TASK_UNMAPPED_BASE in PPC is defined to:
#define TASK_UNMAPPED_BASE (TASK_SIZE / 8 *3) which is 0x30000000
in glibc ldso's JMP_SLOT you have:
{
Elf32_Sword delta = finaladdr - (Elf32_Word) reloc_addr;
if (delta << 6 >> 6 == delta)
*reloc_addr = OPCODE_B (delta);
else if (finaladdr <= 0x01fffffc || finaladdr >= 0xfe000000)
*reloc_addr = OPCODE_BA (finaladdr);
else
{
Elf32_Word *plt, *data_words;
Elf32_Word index, offset, num_plt_entries;
plt = (Elf32_Word *) D_PTR (map, l_info[DT_PLTGOT]);
offset = reloc_addr - plt;
if (offset < PLT_DOUBLE_SIZE*2 + PLT_INITIAL_ENTRY_WORDS)
{
index = (offset - PLT_INITIAL_ENTRY_WORDS)/2;
num_plt_entries = (map->l_info[DT_PLTRELSZ]->d_un.d_val
/ sizeof(Elf32_Rela));
data_words = plt + PLT_DATA_START_WORDS (num_plt_entries);
data_words[index] = finaladdr;
reloc_addr[0] = OPCODE_LI (11, index * 4);
reloc_addr[1] = OPCODE_B ((PLT_LONGBRANCH_ENTRY_WORDS
- (offset+1))
* 4);
MODIFIED_CODE_NOQUEUE (reloc_addr + 1);
}
else
{
reloc_addr[0] = OPCODE_LIS_HI (12, finaladdr);
reloc_addr[1] = OPCODE_ADDI (12, 12, finaladdr);
reloc_addr[2] = OPCODE_MTCTR (12);
reloc_addr[3] = OPCODE_BCTR ();
MODIFIED_CODE_NOQUEUE (reloc_addr + 3);
}
}
}
break;
The if (delta << 6 >> 6 == delta) is commonly false.
Well, if that is true for you, then you must have a really large app, since
this covers relative branches +/-32M.
If finaladdr is <= 0x01fffffc then the relocation is much cheaper than the
last else statement.
But since TASK_UNMAPPED_BASE is 0x30000000, finaladdr will never be <=
0x01fffffc unless
a shared library asks for a low address.
But nearly nothing loads at 0x30000000, usually only ld.so. The executable
itself (note that I haven't looked at PIE executables yet) is at 0x10000000
and the shared libs are loaded initially below that until that space is
filled and then above ld.so IIRC.
I changed TASK_UNMAPPED_BASE to well under 0x01fffffc and it worked as well.
My question: Why is TASK_UNMAPPED_BASE=0x30000000 and would changing it to
something
less, say 0x00100000 be a problem?
Hmm, might work, but it can also break in subtle ways, cause the shared lib
loading algorithm makes a few assumptions about the used address ranges
IIRC. But I don't see any use for it if you consider what I said above.
Franz.
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
Hi All
Currently TASK_UNMAPPED_BASE in PPC is defined to:
#define TASK_UNMAPPED_BASE (TASK_SIZE / 8 *3) which is 0x30000000
in glibc ldso's JMP_SLOT you have:
[SNIP]
quoted
The if (delta << 6 >> 6 == delta) is commonly false.
Well, if that is true for you, then you must have a really large app, since
this covers relative branches +/-32M.
32M == 0x2000000 which is < 0x30000000-0x10000000
So "branches" to any library function will not fit into the 32M space, right?
quoted
If finaladdr is <= 0x01fffffc then the relocation is much cheaper than the
last else statement.
But since TASK_UNMAPPED_BASE is 0x30000000, finaladdr will never be <=
0x01fffffc unless
a shared library asks for a low address.
But nearly nothing loads at 0x30000000, usually only ld.so. The executable
itself (note that I haven't looked at PIE executables yet) is at 0x10000000
and the shared libs are loaded initially below that until that space is
filled and then above ld.so IIRC.
Yes, thats true for glibc. I wonder why glibc supply its own load address for all
libs but ld.so?
However, I forgot to mention uClibc. UClibc does not insist on its own load address, but lets
the kernel handle that. So for uClibc, ld.so will load at 0x30000000 and the rest will follow
after ld.so.
quoted
I changed TASK_UNMAPPED_BASE to well under 0x01fffffc and it worked as well.
My question: Why is TASK_UNMAPPED_BASE=0x30000000 and would changing it to
something
less, say 0x00100000 be a problem?
Hmm, might work, but it can also break in subtle ways, cause the shared lib
loading algorithm makes a few assumptions about the used address ranges
IIRC. But I don't see any use for it if you consider what I said above.
OK, but are there other considerations as well? What is the address space below 0x10000000 used for?
Jocke
From: Peter Bergner <hidden> Date: 2004-02-04 14:37:21
On Tue, 2004-02-03 at 09:22, Franz Sirl wrote:
At 14:05 03.02.2004, Joakim Tjernlund wrote:
quoted
I changed TASK_UNMAPPED_BASE to well under 0x01fffffc and it worked as well.
My question: Why is TASK_UNMAPPED_BASE=0x30000000 and would changing it to
something less, say 0x00100000 be a problem?
Hmm, might work, but it can also break in subtle ways, cause the shared lib
loading algorithm makes a few assumptions about the used address ranges
IIRC. But I don't see any use for it if you consider what I said above.
I've seen problems with HPC apps/benchmarks with huge bss's that fail to
run because TASK_UNMAPED_BASE is set too low. I'll admit they fail to
run due to a bug in the fs/binfmt_elf.c, but the fix has never been
accepted yet. The bug is that we don't reserve the bss region for the
app (via a set_brk/do_brk call) until after we've loaded the loader so
they get mapped to overlapping memory locations. The fix is to move the
update to current->mm.* and the set_brk/do_brk call to before the point
we call load_elf_interp().
Another bug is that the calls to set_brk/do_brk in fs/binfmt_elf.c fail to
check whether the set_brk/do_brk calls succeeded or not, so they implicitly
assume they do. With an app with a huge bss, the set_brk/do_brk call actually
returns -ENOMEM which is then ignored. The fix is to test for failure from
the set_brk/do_brk calls.
Peter
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
From: Anton Blanchard <hidden> Date: 2004-02-04 14:47:07
I've seen problems with HPC apps/benchmarks with huge bss's that fail to
run because TASK_UNMAPED_BASE is set too low. I'll admit they fail to
run due to a bug in the fs/binfmt_elf.c, but the fix has never been
accepted yet. The bug is that we don't reserve the bss region for the
app (via a set_brk/do_brk call) until after we've loaded the loader so
they get mapped to overlapping memory locations. The fix is to move the
update to current->mm.* and the set_brk/do_brk call to before the point
we call load_elf_interp().
Another bug is that the calls to set_brk/do_brk in fs/binfmt_elf.c fail to
check whether the set_brk/do_brk calls succeeded or not, so they implicitly
assume they do. With an app with a huge bss, the set_brk/do_brk call actually
returns -ENOMEM which is then ignored. The fix is to test for failure from
the set_brk/do_brk calls.
A patch went into 2.6 that should fix both of these problems. Give all
those nasty test cases another run :)
Anton
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
From: Peter Bergner <hidden> Date: 2004-02-04 21:58:56
On Wed, 2004-02-04 at 08:47, Anton Blanchard wrote:
A patch went into 2.6 that should fix both of these problems. Give all
those nasty test cases another run :)
Ahh, good. I must have blinked at the wrong time and missed it getting
merged! :-) Do you know whether it got pushed to 2.4 as well?
Peter
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
I changed TASK_UNMAPPED_BASE to well under 0x01fffffc and it worked
as well.
My question: Why is TASK_UNMAPPED_BASE=0x30000000 and would
changing it to something less, say 0x00100000 be a problem?
Hmm, might work, but it can also break in subtle ways, cause the
shared lib loading algorithm makes a few assumptions about the used
address ranges IIRC. But I don't see any use for it if you consider
what I said above.
I've seen problems with HPC apps/benchmarks with huge bss's that fail
to run because TASK_UNMAPED_BASE is set too low.
Too low, does that mean TASK_UNMAPED_BASE < 0x00100000 will fail with
huge bss's as well? Or will it just fail for
0x30000000 => TASK_UNMAPED_BASE <= 0x10000000?
To me it seems like it is a good idea to change(at least in 2.6
where the bugs you mentioned has been fixed) TASK_UNMAPED_BASE to
0x00100000(or lower).
Is there a way I can tell glibc to load it's libs around TASK_UNMAPED_BASE?
Currently only ld.so follows TASK_UNMAPED_BASE, the other libs always
loads at 0x0fxxxxxx. Glibc/ld.so version is 2.2.3
Jocke
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
From: Peter Bergner <hidden> Date: 2004-02-05 16:34:18
On Thu, 2004-02-05 at 02:57, Joakim Tjernlund wrote:
Too low, does that mean TASK_UNMAPED_BASE < 0x00100000 will fail with
huge bss's as well? Or will it just fail for
0x30000000 => TASK_UNMAPED_BASE <= 0x10000000?
To me it seems like it is a good idea to change(at least in 2.6
where the bugs you mentioned has been fixed) TASK_UNMAPED_BASE to
0x00100000(or lower).
The problem with a TASK_UNMAPPED_BASE that was "too low" was referring to
the bug where we always loaded ld.so at TASK_UNMAPPED_BASE even though
that adress was in the middle of the bss. Now that has been fixed, "too low"
isn't a concern anymore.
However, I'm not sure moving the TASK_UNMAPPED_BASE below the text section
will work. It's used for more than just loading shared libs. Anonymous mmap
areas and the heap are all located relative to it.
Is there a way I can tell glibc to load it's libs around TASK_UNMAPED_BASE?
Currently only ld.so follows TASK_UNMAPED_BASE, the other libs always
loads at 0x0fxxxxxx. Glibc/ld.so version is 2.2.3
IIRC, only ppc32 loads it's libs this way. For example, ppc64 loads all
its libs above TASK_UNMAPPED_BASE.
H��lsningar,
Peter
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
From: Anton Blanchard <hidden> Date: 2004-02-05 17:06:57
The problem with a TASK_UNMAPPED_BASE that was "too low" was referring to
the bug where we always loaded ld.so at TASK_UNMAPPED_BASE even though
that adress was in the middle of the bss. Now that has been fixed, "too low"
isn't a concern anymore.
However, I'm not sure moving the TASK_UNMAPPED_BASE below the text section
will work. It's used for more than just loading shared libs. Anonymous mmap
areas and the heap are all located relative to it.
That reminded me of a patch wli did to rearrange how things are
allocated. I wonder if doing something radical like this will work on
ppc32.
Anton
diff -purN -X /home/mbligh/.diff.exclude 400-less_bouncy/arch/i386/Kconfig 410-topdown/arch/i386/Kconfig
On Thu, 2004-02-05 at 02:57, Joakim Tjernlund wrote:
quoted
Too low, does that mean TASK_UNMAPED_BASE < 0x00100000 will fail
with huge bss's as well? Or will it just fail for 0x30000000 =>
TASK_UNMAPED_BASE <= 0x10000000?
To me it seems like it is a good idea to change(at least in 2.6
where the bugs you mentioned has been fixed) TASK_UNMAPED_BASE to
0x00100000(or lower).
The problem with a TASK_UNMAPPED_BASE that was "too low" was referring
to the bug where we always loaded ld.so at TASK_UNMAPPED_BASE even
though that adress was in the middle of the bss. Now that has been
fixed, "too low" isn't a concern anymore.
OK, thanks.
However, I'm not sure moving the TASK_UNMAPPED_BASE below the text
section will work. It's used for more than just loading shared libs.
Anonymous mmap areas and the heap are all located relative to it.
hmm, I have tried several values, for instance anything 0x2000 between
(0x10000000-0x16000) appears to work. (0x10000000-0x15000) don't boot,
but then I am on 2.4, so maybe it's the huge bss bug that bites me.
quoted
Is there a way I can tell glibc to load it's libs around
TASK_UNMAPED_BASE? Currently only ld.so follows TASK_UNMAPED_BASE,
the other libs always loads at 0x0fxxxxxx. Glibc/ld.so version is
2.2.3
IIRC, only ppc32 loads it's libs this way. For example, ppc64 loads
all its libs above TASK_UNMAPPED_BASE.
The problem with a TASK_UNMAPPED_BASE that was "too low"
was referring to the bug where we always loaded ld.so at
TASK_UNMAPPED_BASE even though that adress was in the middle of the
bss. Now that has been fixed, "too low" isn't a concern anymore.
However, I'm not sure moving the TASK_UNMAPPED_BASE below the text
section will work. It's used for more than just loading shared libs.
Anonymous mmap areas and the heap are all located relative to it.
That reminded me of a patch wli did to rearrange how things are
allocated. I wonder if doing something radical like this will work on
ppc32.
[SNIP patch]
Hi Anton
I tried your patch on my 2.4 kernel.
uClibc boots fine with the libs loaded towards lower addresses.
glibc won't boot, hangs direcly after mount.
Jocke
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/