What matters is that the behaviour was specifically changed to load the .text/.plt segment in one go, mainly to make the PLT stuff work for dynamic objects. So, we know what the correct thing is for binutils to do now.
So, the matter is .rodata placed in the same place where .plt are ..
Maybe issue is that .plt should be last section in the segment ? I mean, exactly the final one of some segment, and then .rodata can be anywhere else just not with .plt ?
Quote:
If there are still issues with ctors/dtors not working, even when .rodata placed in a separate read only segment, I'm happy to check the relevant code in the latest elf.library (I believe Alfkil changed it so that it calls the ctors/dtors directly, right?). Just point me in the direction of a compiled test case, so I can reproduce the issue here.
What Max tried after we have those crashes with .sobjs when .rodata is in the same place where .plt are , is just set by default WRITABLE_RODATA= in default ldscript settings for tests: so LD put .rodata now to another RW area of segments, and then sobjs start to work, but then issue with ctros/dtors arise.
That what we have once set in ld linker code WRITABLE_RODATA to be true:
test_dyn binary itself:
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x01000034 0x01000034 0x000a0 0x000a0 R 0x4
INTERP 0x0000d4 0x010000d4 0x010000d4 0x00011 0x00011 R 0x1
[Requesting program interpreter: /usr/lib/ld.so.1]
LOAD 0x000000 0x01000000 0x01000000 0x05000 0x05000 R E 0x10000
LOAD 0x005000 0x01015000 0x01015000 0x00188 0x001e0 RW 0x10000
DYNAMIC 0x005010 0x01015010 0x01015010 0x000b8 0x000b8 RW 0x4
Probably shifting of section and not having rodata as separate segment broke elf.library parsing somehow.. I.e. binaries works , just this ctros/dtros test case didn't pass anymore. Or maybe issue that place where ctors/dtors are cant be expanded by anything new, and elf parser hardcoded on something..
And that where Max stops for now : we do have working binary, .so works too, but just .rodata as RW and not as single R segment R.
Maybe what we need next is to have .rodata as single segment with R firstly, and see if it will autofix things..
Yes, .rodata must not be in the same segment as the .text/.plt segment. Also, .text and .plt must be placed together in the same segment - it shouldn't matter where .plt is in the segment, just as long as the branches into the PLT are correct.
Obviously, .rodata should be placed in read-only segment, not a writable segment - it doesn't need to be executable.
So, with your "rodata_rw" test case, what exactly is the issue? Here, with elf.library 53.42, I get the output:
6> ram:rodata_rw/test_dyn
ctor
ctor2
function 123
main result 123
6>
Slightly curious that the output from the dtors functions does not appear, yet with ELF.debug set to 1, it is clear that it is running the dtors functions.
@Futuara Dtor and dtor2 printf missing from this test case, but, not only that: this code i quote (at end of previous message) print nothing as well, but should print ctor/dtor too. Anyway, if we can got why dtor and dtor2 not prints in rodata_rw test case we may know what wrong.
With adtools binutils build dtor/dtor2 prints fine of course
I think you'll find dtor and dtor2 are actually being successfully called - by that point, it looks like the c lib has possibly been shut down beforehand, so there is no output with puts/printf. Add DebugPrintF to dtor and dtor2 and you will see that.
I'm finding this to be the case with a simple static test and no dynamic objects. No dtor/dtor2 output when compiling with newlib, but works fine with clib2.
I also note that in newlib 53.84, there was this change:
Quote:
Changed the initial .ctors/.dtors sentinel entries from NULL to 0xffffffff to conform with the ELF standard.
This makes the ctors/dtors crash (as elf.library tries to execute address 0xfffffffc instead of skipping this entry), when I try to recompile your test code here.
I think you'll find dtor and dtor2 are actually being successfully called - by that point, it looks like the c lib has possibly been shut down beforehand, so there is no output with puts/printf. Add DebugPrintF to dtor and dtor2 and you will see that.
Interesting.. strange why printfs ok with adtools builds..
Btw, i just tried this rodata_rw test case on emulators, where i have elf.library 53.30 (10/27/2019): and it is simple printf "ctor" and then crashes :) While adtools build runs fine on the same elf.library and didn't crash. Then i update elf.library to 53.42 (04/13/2023) – and crash gone, and it also print correctly:
ctor
ctor2
function 123
main result 123
dtor2
dtor
And that with newlib build (through this on newlib.library 53.62 (01/01/2021) ).
Quote:
Changed the initial .ctors/.dtors sentinel entries from NULL to 0xffffffff to conform with the ELF standard.
This makes the ctors/dtors crash (as elf.library tries to execute address 0xfffffffc instead of skipping this entry), when I try to recompile your test code here.
Tried rodata_rw with newlib 53.84 - no, didn't crash. Also tried this test case i quoted above – also didn't crash… That on WinUAE and with this new binutils
Edited by kas1e on 2023/9/10 5:10:56 Edited by kas1e on 2023/9/10 5:51:00 Edited by kas1e on 2023/9/10 5:58:21 Edited by kas1e on 2023/9/10 6:00:00 Edited by kas1e on 2023/9/10 10:07:08
Which version was the older elf.library that you were using (you quoted the newlib version instead)?
There are several elements involved here:
1. Prior to elf.library 53.37, __shlib_call_(de)constructors() was called (located in SDK:newlib/shcrtbegin.o). With 53.37 or higher, it doesn't use that anymore and instead directly reads .ctors/.dtors and executes the functions specified there.
2. No matter which binutils, compiler or newlib.library you are using, you also have to consider which version of the newlib dev stuff that you have installed in SDK:newlib/lib - for example, the new startup code supplied with 53.84 that sets the initial .ctors/.dtors entry to 0xffffffff instead of 0, which causes elf.library to crash. If you update only "newlib.library.kmod" and leave SDK:newlib/lib as some older version, it won't crash. Likewise if you use some older "newlib.library.kmod", but have SDK:newlib/lib at 53.84, it will still crash.
In my case, I only have the official native compilers and binutils installed, from SDK 54.6, including GCC 8 and 11, plus 4.0.4 and 4.2.4 from older SDKs. No matter what I use, dtor and dtor2 will not print when using newlib (latest SDK:newlib from 53.84), only clib2 works. I'm going to assume this is a bug and that the deconstructors are being called too late in newlib, so I'll file a Bugzilla ticket for that if there isn't already one there.
Regarding elf.library, I've already fixed the 0xffffffff .ctor/.dtor handling and I've tested that it doesn't crash anymore, which will be available when I upload 53.43 for beta testing.
For the new binutils, the change that is required is to ensure the .rodata section is placed in its own read-only segment by itself for dynamic objects, just as the old binutils does. It is not a good idea to put any other sections in the segment holding .rodata, due to previously discussed reasons.
Which version was the older elf.library that you were using (you quoted the newlib version instead)?
Right, fixed. It was 53.30 (10/27/2019).
Quote:
1. Prior to elf.library 53.37, __shlib_call_(de)constructors() was called (located in SDK:newlib/shcrtbegin.o). With 53.37 or higher, it doesn't use that anymore and instead directly reads .ctors/.dtors and executes the functions specified there.
So it means then, that older way didn't work with rodata_rw test case, and calling __shlib_call_(de)constructors() cause issues with. One more bug then when rodata is in RW and not as independent section.
Quote:
If you update only "newlib.library.kmod" and leave SDK:newlib/lib as some older version, it won't crash.
Yes, you are right, just forgot about. Good that you sort it out.
Quote:
No matter what I use, dtor and dtor2 will not print when using newlib (latest SDK:newlib from 53.84), only clib2 works. I'm going to assume this is a bug and that the deconstructors are being called too late in newlib, so I'll file a Bugzilla ticket for that if there isn't already one there.
Or, the fact that rodata_rw test case print all fine on WinUAE for me, may point out on some timing issues ?
Quote:
For the new binutils, the change that is required is to ensure the .rodata section is placed in its own read-only segment by itself for dynamic objects, just as the old binutils does. It is not a good idea to put any other sections in the segment holding .rodata, due to previously discussed reasons.
Right, for first we should have .rodate as R and be independent. But, with old binutils, most time, .rodata comes not alone, but with .__newlib_version together in one area, like this:
03 .rodata .__newlib_version
Quote:
Let me know if I have missed anything?
Probably all clear now, to sort it out we need:
1). Make new binutils to have .rodata as independent and marked as R 2). Check after, if elf.library prior 53.37, if this .so test case passes and didn't crashes. If it still, then another bug to fix 3). Check after, if ctor/dtor and ctor2/dtor2 prinfs fine with test case be it newlib or clib2
After all done, we can go checking how make working .init_array / .fini_array. As i see in changelog for elf.library, alfkil add support of it, but it's untested.
See, there ppls ask "why .rodata is in the segments which RW, and not independent segment", and some answer like "because .rodata not really read only".
So it starts to looks like, that newer binutils may have by default put .rodata to the RW or RE bunch of sections, but then, is it done lately (after our adtools version of binutils), or it were changed specially somehow in old binutils - dunno.
Anyway, for sake of test i going that way: i just dump the inbuild ldscript via "-Wl,-verbose", and there replace that:
I.e. simple add 333 (which make loadable new segment, but don't ask me what those numbers are, just taken them elsewhere from google for tests). Then used new ldscript via -T, and this script create for me .rodata section to be independend and with "R", so test case start to looks like this with new binutils:
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x00000034 0x00000034 0x000c0 0x000c0 R 0x4
INTERP 0x0100f4 0x010000f4 0x010000f4 0x00011 0x00011 R 0x1
[Requesting program interpreter: /usr/lib/ld.so.1]
LOAD 0x000000 0x00000000 0x00000000 0x00200 0x00200 R 0x10000
LOAD 0x000200 0x00010200 0x00010200 0x000d8 0x00130 RW 0x10000
LOAD 0x0100f4 0x010000f4 0x010000f4 0x038f4 0x03f84 R E 0x10000
DYNAMIC 0x000210 0x00010210 0x00010210 0x000b8 0x000b8 RW 0x4
But sadly, rebuild both libf.so and test_dyn and to have correct .rodata placed independent and marked as R , didn't fix issue with crash on previous elf.library :(
And crash is 0x200000000 symbol not available.
Edited by kas1e on 2023/9/10 14:24:47 Edited by kas1e on 2023/9/10 14:26:05
I'm not 100% sure, but I don't think elf.library works that way. Instead of using traps which resolve it on first access it loads all .so used by the executable and resolves everything before _start() in the executable is called.
That's the other variant. Same, same but different, just takes longer during startup, because no lazy resolving.
@Futaura
Quote:
Quote:
Program header loadable segments are now loaded as segment even if they are executable. This caused some problems with older binaries that have .text and .rodata in the same segment; if the loader detects such a segment, it is ignored and the sections are loaded separately. This behaviour is required because the PLT must be correctly placed relative to the text segment.
So instead of using the program headers (segments) to allocated memory as described by the elf file, the elf.library allocates memory by sections? I thought that this is one of the smart ideas of the elf file format, that a linker just allocates memory as describes and than populate it from the content, resp. fills its as described by the ABI.
And you say, that is because of the support of M68k stubs stuff?
Quote:
Quote:
Changed the initial .ctors/.dtors sentinel entries from NULL to 0xffffffff to conform with the ELF standard.
This makes the ctors/dtors crash (as elf.library tries to execute address 0xfffffffc instead of skipping this entry), when I try to recompile your test code here.
Mhh, that could be case why stuff crashes with new binutils. But i read further down that this is already fixed in new elf.library. And that ctor/dtor stuff heavily even depends on the used c library.
@kas1e
Quote:
Probably all clear now, to sort it out we need:
1). Make new binutils to have .rodata as independent and marked as R 2). Check after, if elf.library prior 53.37, if this .so test case passes and didn't crashes. If it still, then another bug to fix 3). Check after, if ctor/dtor and ctor2/dtor2 prinfs fine with test case. be it newlib or clib2
After all done, we can go checking how make working .init_array / .fini_array. As i see in changelog for elf.library, alfkil add support of it, but it's untested.
Ok, so for binutils elft to be realized is point 1, to have new binutils to behave like old ones. Maybe the 333 isn't absolut correct, will investigate on it.
So instead of using the program headers (segments) to allocated memory as described by the elf file, the elf.library allocates memory by sections? I thought that this is one of the smart ideas of the elf file format, that a linker just allocates memory as describes and than populate it from the content, resp. fills its as described by the ABI.
Yes, well the normal case is that elf.library scans the program headers and allocates a memory block to hold each segment. Then, if/when it needs to load a section, the section is loaded into the defined location in the segment.
However, currently, segments will be ignored if that segment contains .rodata. Then, instead of the above, each section is allocated individually later when it needs to be loaded. This means even for the old binutils when .rodata is in its own segment, that segment is ignored too.
For the next elf.library, I'm tweaking this slightly, so that segments will always be loaded in their entirety, unless the segment contains .rodata and an executable section (i.e. old binutils where .rodata and .text were placed in the same segment).
Quote:
And you say, that is because of the support of M68k stubs stuff?
That's what the comment eluded too, but I've still yet to get my head around exactly why. I vaguely remember that in the old days the stubs, which we asm based back then, were maybe not placed in the correct section or something.
Quote:
Quote:
This makes the ctors/dtors crash (as elf.library tries to execute address 0xfffffffc instead of skipping this entry), when I try to recompile your test code here.
Mhh, that could be case why stuff crashes with new binutils. But i read further down that this is already fixed in new elf.library. And that ctor/dtor stuff heavily even depends on the used c library.
Certainly if you are seeing ISI errors with the instruction pointer at 0xfffffffc, or thereabouts, that will be the reason. I think the whole reason Alfkil changed elf.library to use .ctors/dtors directly, instead of relying on __shlib_call_constructors(), was to make it independent of newlib/clib2 (and to handle broken apps that had unterminated ctor/dtor arrays). It wouldn't have been a problem if the recent change to newlib had been mirrored in elf.library at the same time.
The dtors not working correctly is almost certainly a bug in newlib.library and I've filed a report for that so hopefully it gets fixed soon.
(Un)fortunately, I got carried away with fixing these things in elf.library and have fixed and improved some other things too. I should be working in a different project, but whilst I have all these issues and inner workings of elf.library in my head, it's best to flush them all out before I forget .
@Oliver While you at it (thanks a bunch!) can you please also check if adding of fini/init arrays support by Alfkil expected to be working ? When we tryied some time ago to build new binutils with it's support, it was still forced to dtors/ctors, and reading comments of the commit to elf.library where alfkil add it, it were marked as "untested", so we not sure if it should works or not :)
And while it looks good, when i run the test case it simple crashes in libf.so:ctor() with "symbol unavailable".
The differences which we have now in compare with adtools's binutils is __newlib_version in adtools were in the same area where .rodata was, but in our current case currently we keep it in the one where .text and .plt are. But can it be cause of crash ?
Thanks for the hint with the debug output for the elf.library. It gives more information, but still the picture isn't as clear as wanted.
Because the message
Quote:
Ignoring this program header because we have an .rodata segment
Is even issued for program headers/segments which don't contain a .rodata section. So it must be more than just having a .rodata section in the segment, that the segment is handled differently.
See we have the following segments/sections
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x01000034 0x01000034 0x000c0 0x000c0 R 0x4
INTERP 0x0000f4 0x010000f4 0x010000f4 0x00011 0x00011 R 0x1
[Requesting program interpreter: /usr/lib/ld.so.1]
LOAD 0x000000 0x01000000 0x01000000 0x050b0 0x050b0 R E 0x10000
LOAD 0x015000 0x01005000 0x01005000 0x000a5 0x000a5 R 0x10000
LOAD 0x020000 0x01010000 0x01010000 0x000d8 0x00130 RW 0x10000
DYNAMIC 0x020010 0x01010010 0x01010010 0x000b8 0x000b8 RW 0x4
And this is the beginning of the elf.library debug output with two times the message
[Elf32_LoadSection] On Entry SectionIndex = 37 Filename = Work:2/test_dyn
[Elf32_LoadSection] sec = 0x5FFE9000
[Elf32_LoadProgramHeaders] File: Work:2/test_dyn
[Elf32_LoadProgramHeaders] Program Header offset: 0x00000034
[Elf32_LoadProgramHeaders] Program Header entrysize: 32
[Elf32_LoadProgramHeaders] Program Header array size: 6
[Elf32_LoadProgramHeaders] ProgHeader 0: Type 6
[Elf32_LoadProgramHeaders] Virtual: 0x01000034
[Elf32_LoadProgramHeaders] MemSize: 0x000000C0
[Elf32_LoadProgramHeaders] Flags: 0x00000004
[Elf32_LoadProgramHeaders] ProgHeader 1: Type 3
[Elf32_LoadProgramHeaders] Virtual: 0x010000F4
[Elf32_LoadProgramHeaders] MemSize: 0x00000011
[Elf32_LoadProgramHeaders] Flags: 0x00000004
[Elf32_LoadProgramHeaders] ProgHeader 2: Type 1
[Elf32_LoadProgramHeaders] Virtual: 0x01000000
[Elf32_LoadProgramHeaders] MemSize: 0x000050B0
[Elf32_LoadProgramHeaders] Flags: 0x00000005
[Elf32_LoadProgramHeaders] Ignoring this program header because we have an .rodata segment
[Elf32_LoadProgramHeaders] ProgHeader 3: Type 1
[Elf32_LoadProgramHeaders] Virtual: 0x01005000
[Elf32_LoadProgramHeaders] MemSize: 0x000000A5
[Elf32_LoadProgramHeaders] Flags: 0x00000004
[Elf32_LoadProgramHeaders] Ignoring this program header because we have an .rodata segment
[Elf32_LoadProgramHeaders] ProgHeader 4: Type 1
[Elf32_LoadProgramHeaders] Virtual: 0x01010000
[Elf32_LoadProgramHeaders] MemSize: 0x00000130
[Elf32_LoadProgramHeaders] Flags: 0x00000006
[Elf32_LoadProgramHeaders] Allocated 304 bytes for segment 0 at 0x61DCF040
[Elf32_LoadProgramHeaders] ProgHeader 5: Type 2
[Elf32_LoadProgramHeaders] Virtual: 0x01010010
[Elf32_LoadProgramHeaders] MemSize: 0x000000B8
[Elf32_LoadProgramHeaders] Flags: 0x00000006
[_elf32_ElfLoadSeg] Entry
[Elf32_LoadSection] On Entry SectionIndex = 35 Filename = Work:2/test_dyn
[Elf32_LoadSection] ehdr->e_shstrndx = 37, shdr->sh_name = 1
Even that the second output of the message can be explained with, what you sad: a .rodatas section in segment. The first message have been triggered by another condition.
Could peek in the source of the elf.library and see if you find another/additional explaination?
Sorry for the delayed reply - have been busy attempting to rewrite the reloc code in elf.library, so that it's easier to understand and less easy to break in the future, which might not be possible!
@MigthyMax
This looks like a linker issue to me - segment 2 and 3 overlap, which shouldn't happen:
ELF.debug is levelled also - can be set 1-9 (maybe higher too). The higher the value, the more debug you get.
@kas1e
I don't have anything to test it with, as I don't think I have anything with a .fini_array and .init_array in them, or anything that can generate them. However, it looks like it should work fine, but the current logic involved is that it looks for .ctors first, and if .ctors is not present, it then looks for .init_array instead. Same for .dtors and .fini_array. So, if you were to have both in the file, .ctors/dtors will always get used.
Ok, that was obviously. But it even output the debug message for other circumstances, where no overlap is (as long i can see, maybe i have a blind spot on this) and the .rodata section isn't in the segment like this from this debug output:
[Elf32_LoadSection] On Entry SectionIndex = 37 Filename = Work:1/test_dyn
[Elf32_LoadSection] sec = 0x60C11000
[Elf32_LoadProgramHeaders] File: Work:1/test_dyn
[Elf32_LoadProgramHeaders] Program Header offset: 0x00000034
[Elf32_LoadProgramHeaders] Program Header entrysize: 32
[Elf32_LoadProgramHeaders] Program Header array size: 6
[Elf32_LoadProgramHeaders] ProgHeader 0: Type 6
[Elf32_LoadProgramHeaders] Virtual: 0x01000034
[Elf32_LoadProgramHeaders] MemSize: 0x000000C0
[Elf32_LoadProgramHeaders] Flags: 0x00000004
[Elf32_LoadProgramHeaders] ProgHeader 1: Type 3
[Elf32_LoadProgramHeaders] Virtual: 0x010000F4
[Elf32_LoadProgramHeaders] MemSize: 0x00000011
[Elf32_LoadProgramHeaders] Flags: 0x00000004
[Elf32_LoadProgramHeaders] ProgHeader 2: Type 1
[Elf32_LoadProgramHeaders] Virtual: 0x01000000
[Elf32_LoadProgramHeaders] MemSize: 0x000050B0
[Elf32_LoadProgramHeaders] Flags: 0x00000005
[Elf32_LoadProgramHeaders] Ignoring this program header because we have an .rodata segment
[Elf32_LoadProgramHeaders] ProgHeader 3: Type 1
[Elf32_LoadProgramHeaders] Virtual: 0x01010000
[Elf32_LoadProgramHeaders] MemSize: 0x00000130
[Elf32_LoadProgramHeaders] Flags: 0x00000006
[Elf32_LoadProgramHeaders] Allocated 304 bytes for segment 0 at 0x60D907C0
[Elf32_LoadProgramHeaders] ProgHeader 4: Type 2
[Elf32_LoadProgramHeaders] Virtual: 0x01010010
[Elf32_LoadProgramHeaders] MemSize: 0x000000B8
[Elf32_LoadProgramHeaders] Flags: 0x00000006
[Elf32_LoadProgramHeaders] ProgHeader 5: Type 1
[Elf32_LoadProgramHeaders] Virtual: 0x01005000
[Elf32_LoadProgramHeaders] MemSize: 0x000000A5
[Elf32_LoadProgramHeaders] Flags: 0x00000004
[Elf32_LoadProgramHeaders] Ignoring this program header because we have an .rodata segment
@Oliver We with Max tried to go another route: we use SEPARATE_CODE options in binutils (so it put .rodata in different segment and not together with .text and .plt), but then, together with that, we have some unwanted eh_frame segment, which may (or may not) made an impact how our elf.library reacts.
With this new way, we do have some strange issue : static builds works fine, and all ok, but when it comes to the .so support, we have crash right once we tried to use anything from this .so.
More of it, if we use our new .so created from our new binutils, but main binary created by old adtool's binutils, then we NOT crash. So the issue is exactly how we construct the main binary.
If you can, plz, give a look at what we have now, maybe you will spot something obviously wrong there which we miss (or, maybe you will see that what we have, is bad for our elf.library somehow ..).
There is archive in which 2 directories : one is test case build with adtools, and another one test case build with new binutils:
As you can see all it does, it just .so have simple functions with printf inside, and we just call from the main binary this function, so basic and simple as it ever can be.
To not loose your time (if you don't want to download archive at all), there is what we have:
adtool's version of libhello.so:
$ ppc-amigaos-readelf -l libhello.so
Elf file type is DYN (Shared object file)
Entry point 0x100002b0
There are 4 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x10000000 0x10000000 0x003f0 0x01054 R E 0x10000
LOAD 0x002000 0x10002000 0x10002000 0x00010 0x00010 R 0x10000
LOAD 0x002010 0x10012010 0x10012010 0x000d4 0x000d4 RW 0x10000
DYNAMIC 0x00202c 0x1001202c 0x1001202c 0x000a8 0x000a8 RW 0x4
And i should point out again that when i use our new .sobj (with that eh_frame in), but _old_ main binary from adtools build, then it still works fine. Probably mean, that sobj is ok, and eh_frame also of no problem, but issue is the main binary and something in. And from sections, all the difference i see is that .rodata and __newlib_version are separate. But again, it shouldn't probably cause issues ?
Anyway, i also do "elf_debug 1", and catch output for both : working version from adtools (with .so created from new binutils), and our, non working version from new binutils (with same .so),and that what i got :
Maybe you can spot anything, it will be of huge help ! At least we can know to what look at. But as our new sobj works with old main binary from adtools, but didn't with new one, issue is then in the new binary and probably re-calculation of some addresses or something ..
From what you say, regarding the different variations, I'd have to agree that it is going to be the new executable that is the problem. The crash is PLT related - either the PLT not being updated or the jumps in the code not reaching the PLT.
The obvious differences - the old binutils test_dyn:
Relocation section '.rela.plt' at offset 0x468 contains 3 entries:
Offset Info Type Sym.Value Sym. Name + Addend
01004048 00000315 R_PPC_JMP_SLOT 01004048 hello + 0
01004050 00000415 R_PPC_JMP_SLOT 01004050 memcpy + 0
01004058 00000e15 R_PPC_JMP_SLOT 01004058 gettimeofday + 0
Relocation section '.rela.text' at offset 0x1a334 contains 211 entries:
Offset Info Type Sym.Value Sym. Name + Addend
01003998 0000380a R_PPC_REL24 01004048 hello + 0
Symbol table '.dynsym' contains 21 entries:
Num: Value Size Type Bind Vis Ndx Name
3: 01004048 0 FUNC GLOBAL DEFAULT UND hello
4: 01004050 0 FUNC GLOBAL DEFAULT UND memcpy
Symbol table '.symtab' contains 99 entries:
Num: Value Size Type Bind Vis Ndx Name
56: 01004048 0 FUNC GLOBAL DEFAULT UND hello
57: 01004050 0 FUNC GLOBAL DEFAULT UND memcpy
Compared with the new binutils:
Relocation section '.rela.plt' at offset 0x468 contains 3 entries:
Offset Info Type Sym.Value Sym. Name + Addend
01004048 00000315 R_PPC_JMP_SLOT 00000000 hello + 0
01004050 00000415 R_PPC_JMP_SLOT 00000000 memcpy + 0
01004058 00000d15 R_PPC_JMP_SLOT 00000000 gettimeofday + 0
Relocation section '.rela.text' at offset 0x25584 contains 211 entries:
Offset Info Type Sym.Value Sym. Name + Addend
01003998 00003a0a R_PPC_REL24 00000000 hello + 0
Symbol table '.dynsym' contains 21 entries:
Num: Value Size Type Bind Vis Ndx Name
3: 00000000 0 FUNC GLOBAL DEFAULT UND hello
4: 00000000 0 FUNC GLOBAL DEFAULT UND memcpy
Symbol table '.symtab' contains 99 entries:
Num: Value Size Type Bind Vis Ndx Name
58: 00000000 0 FUNC GLOBAL DEFAULT UND hello
59: 00000000 0 FUNC GLOBAL DEFAULT UND memcpy
I think this is kind of linked to Alfkil's pointer equality "fix" in elf.library. I had to undo some of that for R_PPC_REL24 relocs because his change caused crashes due to out of range 24-bit branches. So, you might find your test doesn't crash with elf.library 53.46 (will crash with newer versions). Likewise if you re-add the patch that stops st_value being set to zero, it shouldn't crash.
However, I'm not sure any of that is a proper solution, so the big question is what is the correct solution? I'm happy to adjust elf.library, but how... Ideally, which I tried the other day, is that R_PPC_REL24 relocs could be ignored because the relative branches are already in the code usually (however, I found some cases where the reloc needed to be applied - newlib calls in some libraries). I suppose elf.library could be changed to ignore R_PPC_REL24 relocs completely if st_value is 0, which might solve these crashes.
Edit: Just tried my own suggestion above and your new binutils test_dyn is now working fine. If you can confirm your new binutils test_dyn doesn't crash with elf.library 53.46, it would make me a bit happier that this fix is the correct thing to do. FYI, once we can confirm that elf.library is handling things correctly and fully fixed, I'm going to bump it to v54.
@Oliver Tested! With 54.46 this test case surely didn't crash and works! Question is : can we keep it like this in binutils now ? While you can ignore R_PPC_REL24 relocs completely if st_value is 0 : question is : should we keep binutils code in place which didn't calculate correctly relocs ?
Because it also will mean that new created binaries will be not able to works on anything which is less than 54.46 of elf.library ?
I also tried the previous test case (the one i uploaded to os4beta before), which just:
See, libf.so has now .init_array and .fini_array (together with .ctors and .dtors), but i have no printfs not from init/fini, not from ctros/dtors. Is is something to be deal in elf.library as well, or in newlib/clib2 ?
The fact that binary itself runs and prinfs, probabaly mean that init/fini or ctors/dtors works, but why no prinfs from consructors/destructors ..
EDIT:
Btw, we find that in adtools version of binutils, in the 0001-Changes-for-various-Amiga-targets.patch, in the bfd/elf32-amigaos.c , the do that:
- sym->st_value = 0;
+ {
+ /* THF: This is peculiar. The compiler generates a R_PPC_REL24 for externally referenced
+ * symbols impoted from libc.so. Relocation in elf.library requires the symbol to have it's .plt
+ * stub value, but the linker specifically clears the value to 0, resulting in run-time
+ * errors when the binary tries to call libc functions.
+ */
+ // sym->st_value = 0;
+ }
So probably that it , they disable it to avoid crashes. While elf.library fix are good, to keep support of working on older elf.library we probably need to do the same in new binutils ?