So this is a linker issue. You might want to look at binutils/bfd/elf32-amigaos.c to see, if you can spot where it happens.
I found the line 9345 int the file you mention causing, that the value in the symbols isn't zero:
...
9328 if (!h->def_regular)
9329 {
9330 /* Mark the symbol as undefined, rather than as
9331 defined in the .plt section. Leave the value if
9332 there were any relocations where pointer equality
9333 matters (this is a clue for the dynamic linker, to
9334 make function pointer comparisons work between an
9335 application and shared library), otherwise set it
9336 to zero. */
9337 sym->st_shndx = SHN_UNDEF;
9338 if (!h->pointer_equality_needed)
9339 {
9340 /* THF: This is peculiar. The compiler generates a R_PPC_REL24 for externally referenced
9341 * symbols impoted from libc.so. Relocation in elf.library requires the symbol to have it's .plt
9342 * stub value, but the linker specifically clears the value to 0, resulting in run-time
9343 * errors when the binary tries to call libc functions.
9344 */
9345 // sym->st_value = 0;
9346 }
9347 else if (!h->ref_regular_nonweak)
...
That should probably be handled more sophisticated.
I'M currently using kas1e 2.24 patch from his provided links, and trying to adapt it on the master of the binutils.
Cool! As far as i can see, i deleted os3/aros/mos code from, it's just keeping in the configure scripts only, which we can later delete too to simplify the process.
After that will be done, it will be much easier to update binutils to further version. But removing the old not-used code will be a start for sure.
I will have to do some further testing. What I have done is to build elf.library to default to symbol lookup for UND symbols. I will have to confirm, that this approach works in general.
There is the caveat, that the 'world' symbol still is not set to 0, only 'hello' and 'printf'. Therefore the solution seems to be to do the default lookup.
When I have done a few more steps on the spot, I will test Qt6 to see, if the new solution improves on performance here.
Ok, so far so good. Qt6 is rebuildt and tested. 'connect()' calls no longer fail, and the relevant ui elements perform as they should. So I just assume, that this means 'it's working'.
Also system performance seems to be unaffected, and the few other applications I have tried seems to perform normally. So - fingers crossed - I think this is a good solution.
Now, before I start donating right and left, I would like the constructor issue to be solved as well. Overall, I think it a good measuring point to require an optimally functioning version of Qt6 before giving out gifts. So : Constructur issue. Any takers?
Ok, so far so good. Qt6 is rebuildt and tested. 'connect()' calls no longer fail, and the relevant ui elements perform as they should. So I just assume, that this means 'it's working'.
Amiga bless the ones who kill the Alf !:) Is it changes was only in the file you with Max point out ? (i just about needs to commit them to adtools repo, so no one will have the same issue again)
I asked Frank (vbcc author) about all those "rel" sections (as Frank is the one who know that stuff very well and often help me with all sort of explains about internals) and that what he says: (i rephrased it a bit to avoid copy+paste of mail content):
Those are 16 or 32 bit base-relative addressing mode, relative to the data segment (r2 register used as a base register). Those addressing mode was mostly used in shared libraries or resident, reentrable code, where you copy the whole data segment on program start with CopyDataSegment() from elf.library.
There is also the linker script symbol _DATA_BASE_, to initialize the base register. But it points into the original data segment. Therefore, to initialize the new base pointer after CopyDataSegment() you either have to know the offset inside the data segment, or calculate the offset from _DATA_BASE_ to the original start address of the data segment and add it to the new address returned by CopyDataSegment (or so).
In assembler code, you would access a symbol in the 16-bit region of the data segment like this
Speaking of which, vbcc do have option -baserel32os4 to enable such data addressing. In the GCC, back in the past, we do use -mbaserel or something, but, issue there that since gcc4.x or something, this was deprecated silently and done with it.
Through, again, i don't know how it all apply to our sobjs issue which we faced there, but at least some bits of info about those relocations sections can help the whole picture.
Amiga bless the ones who kill the Alf !:) Is it changes was only in the file you with Max point out ? (i just about needs to commit them to adtools repo, so no one will have the same issue again)
The current solution is independent of any changes to bfd. I will have to first confer with Steven Solie. If he approves of the solution, he will do the commit and release of the new elf.library. Binutils do not need to be changed.
What I have done is to build elf.library to default to symbol lookup for UND symbols.
I won't go for the general way to perform a lookup. As the ABI states, it should only be made if the value of the symbol is zero and a UNDEF function. It explicitly states that if it if an UNDEF function and value is none zero, use the value. There might b use cases where the linker is able to pre calculated an address which should be used, which we haven't on our radar.
So i think the solution is a combination of a new elf.library and a fixed linker. I even think that the changes made to the linker (as pointed out) has only been introduced, to workaround a problem in past.
Quote:
Constructur issue. Any takers?
I'm so deep now into the linker stuff i will take a look.
Speaking of which, vbcc do have option -baserel32os4 to enable such data addressing. In the GCC, back in the past, we do use -mbaserel or something, but, issue there that since gcc4.x or something, this was deprecated silently and done with it.
Through, again, i don't know how it all apply to our sobjs issue which we faced there, but at least some bits of info about those relocations sections can help the whole picture.
It doesn't have anything to do with the sobjs issues. It just curiosity on my side. An silently done is very interesting because the implementation of the relocs in the binutils apaches are more less uncommented like this:
#if 0
case R_PPC_AMIGAOS_BREL:
case R_PPC_AMIGAOS_BREL_HI:
case R_PPC_AMIGAOS_BREL_LO:
case R_PPC_AMIGAOS_BREL_HA:
{
if (data_section == NULL)
data_section = bfd_get_section_by_name (output_bfd, ".data");
if (sec)
{
const char *name = bfd_get_section_name (abfd, sec->output_section);
if (strcmp (name, ".sdata") != 0
&& strcmp (name, ".sbss") != 0
&& strcmp (name, ".data") != 0
&& strcmp (name, ".bss") != 0
&& strncmp (name, ".ctors", 6) != 0
&& strncmp (name, ".dtors", 6) != 0)
{
(*_bfd_error_handler) (_("%s: The target (%s) of a %s relocation is in the wrong output section (%s)"),
input_bfd,
sym_name,
howto->name,
name);
}
}
I won't go for the general way to perform a lookup. As the ABI states, it should only be made if the value of the symbol is zero and a UNDEF function.
Well, since the amigaos is already performing non-standard compared to the ABI, I think the argument could go either way. One could even argue, that the .plt stubs are obsolete, since they introduce no added functioning, but only helps to clutter the concept of linking. I am not sure, if there is some argument from cyber safety, that necessitates a .plt section. But from a functioning point of view, it is definitely unnecessary.
IF we are to implement the ABI text and allow for linking using the st_value attribute for UNDEF entries, then we still need to figure out, why the 'world' symbol comes out non-zero in the example. Simply uncommenting the line with st_value = 0 doesn't solve that part of the problem.
IF we are to implement the ABI text and allow for linking using the st_value attribute for UNDEF entries, then we still need to figure out, why the 'world' symbol comes out non-zero in the example. Simply uncommenting the line with st_value = 0 doesn't solve that part of the problem.
Currently no idea why it doesn't solve it, except a general issue in the used binutils version.
Actually, when looking at the original non-amiga text (as found in the patches) :
if (!h->pointer_equality_needed)
- sym->st_value = 0;
This is a bit mysterious. From my current perspective, this looks like a bug. The cases, that require pointer equality, are exactly the cases, where we need the st_value parameter to be zero. So this might be just a case of a '!' inserted in the wrong place. It will be interesting to know, what the updated binutils source says in this place.
A reply to myself. After consolidating the binutils 2.40 source, I have found this :
Quote:
if (!local_undefweak && !h->def_regular && (h->plt.offset != (bfd_vma) -1 || eh->plt_got.offset != (bfd_vma) -1)) { /* Mark the symbol as undefined, rather than as defined in the .plt section. Leave the value if there were any relocations where pointer equality matters (this is a clue for the dynamic linker, to make function pointer comparisons work between an application and shared library), otherwise set it to zero. If a function is only called from a binary, there is no need to slow down shared libraries because of that. */ sym->st_shndx = SHN_UNDEF; if (!h->pointer_equality_needed) sym->st_value = 0; }
The important part is the comment. As stated, the binary loader (elf.library) needs to do an active comparison, when the value is non-zero. When zero, it just performs a lookup.
In the current elf.library implementation, the easiest way of meeting this requirement, is to do a default lookup, which will always result in pointer equality. Since the .plt entry is private to the main app (or the specific shared object), there is no way of having pointer equality, when the entry points to the .plt entry. And the only known cases of a non-zero st_value are the ones, where st_value points to .plt.
Actually, when looking at the original non-amiga text (as found in the patches) :
if (!h->pointer_equality_needed)
- sym->st_value = 0;
This is a bit mysterious. From my current perspective, this looks like a bug. The cases, that require pointer equality, are exactly the cases, where we need the st_value parameter to be zero. So this might be just a case of a '!' inserted in the wrong place. It will be interesting to know, what the updated binutils source says in this place.
It's still the same in the current main of binutils. And even for me it looks like an bug. I missed the "!" as i found the location. For me it was obvious that there isn't a "!".
In the current elf.library implementation, the easiest way of meeting this requirement, is to do a default lookup, which will always result in pointer equality. Since the .plt entry is private to the main app (or the specific shared object), there is no way of having pointer equality, when the entry points to the .plt entry. And the only known cases of a non-zero st_value are the ones, where st_value points to .plt.
My personal opinion is to let the elf.library only perform an look up is the value is zero, and to fix binutils to put there a zero.
Does binutils put a zero in if the "!" is removed from the if clause?
Removing the '!' would give zero to 'world'. But I don't think this is the right solution. I think it is best to keep the binutils code as close to the original as possible. I trust it. Instead I suggest to adhere to the workflow, that is maintained and hinted at here. This would mean to ensure pointer equality in the cases, where st_value is non-zero, and that is exactly, what my solution does.
Regarding the constructor issue. As long i understand it is that the elf.library during lodding the libf.so calls the __shlib_call_constructors method, which should call the constructors of the shared object library. From the example given here, it looks like that the test_dyn laods the libf.so and that the gets __shlib_call_constructors. For me it looks like that the implementation of __shlib_call_constructors might be buggy in calling all present constructors:
So can you confirm that elf.library calls __shlib_call_constructors and __shlib_call_destructors when load shared objects thru InitSHLibs?
Well I cannot be 100% sure, because I have no insight in how sobjs loading is implemented. Maybe elfpipe can confirm it/look into it.
But based upon the documentation of the InitSHLibs method of the elf.library and that the failing test still somehow calls one constructor, but both destructors, I conclude that both methods __shlib_call_constructors and __shlib_call_destructors gets called. Furthermore, because they do in the example pretty much the same, they should look a like. But for me the ppc dump, don't like similar enough. I think i have do analyses the ppc code.