[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: [Gcl-devel] Re: gdb for mips64


"Maciej W. Rozycki" <macro@linux-mips.org> writes:

> On Thu, 28 Oct 2010, Camm Maguire wrote:
>> >  Can you quote what `ld --version' says on the affected system?
>> >
>> ld --version
>> GNU ld (GNU Binutils) 2.18
>> Copyright 2007 Free Software Foundation, Inc.
>> This program is free software; you may redistribute it under the terms of
>> the GNU General Public License version 3 or (at your option) a later version.
>> This program has absolutely no warranty.
>  OK, they should be good I believe, as should be any version newer than 
> 2.16-ish (I'd have to get at the ChangeLogs to recall exactly when usable 
> support for the new ABIs went in), but I suggest an upgrade to the current 
> version at your convenience anyway.

OK, this isn't my machine, but good to know.

>> >  A legitimate cause for a stub to be omitted by the linker are pointer 
>> > references to the function in question as in this case the symbol has to 
>> > be fully resolved for pointer comparison to produce reliable results.  It 
>> > could be that one version of GCC produces code that looks to the linker as 
>> > if referring to the symbol this way (i.e. the object files presented to 
>> > the linker contain relocations normally used for data references rather 
>> > than function calls associated with the symbol in question).  You can 
>> > determine if that is the case by running `objdump -r' on the program's 
>> > object files used in the final link and checking if there are any GOT 
>> > relocations (that'll be a part of their names, e.g. R_MIPS_GOT_PAGE) 
>> > against _IO_getc.  Again, that *might* be a GCC bug then.
>> Yep:
>> File: gcl_readline.o
>> 0000000000000928 R_MIPS_GOT_DISP   _IO_getc
>> int rl_getc_em(FILE *f) {
>> 	static char *line = NULL;
>> 	static int linepos = 0;
>> 	int r;
>> 	if (f!=stdin || !isatty(fileno(f)) ) return getc(f);
>> ....
>  OK, so that does look like a problem with GCC as this piece of code only 
> takes the address of getc() (that is #defined to _IO_getc() in <stdio.h>) 
> for the purpose of making a function call.  An R_MIPS_CALL16 relocation 
> should therefore be used here instead.
>  Would you care to quote the GCC version causing this and get an assembly 
> output of the surrounding code (say +/-5 instructions from the 
> relocation), preferably one generated by GCC along the lines of:
> $ gcc -S -dp <other_options_needed_here> gcl_readline.c
> (you can just copy and paste the invocation line quoted by `make' and 
> substitute "-c" for "-S -dp" (and gcl_readline.o for gcl_readline.s, if 
> applicable) leaving the rest of options intact), but if that turns out too 
> difficult, then:
> $ objdump -dr gcl_readline.o
> might be good enough.

OK see attachment below.

>> >  That said the only impact from a missing stub is a small program startup 
>> > performance penalty as lazy binding cannot be applied to this single 
>> > symbol only and the symbol has to be fully resolved at startup.
>> >
>> This comment was very helpful.  I had implemented a stub at the end of
>> each loaded .o file to read the main stub, discern the got entry, read
>> it, and jump.  Now I skip the stub reading step and use the gotsym and
>> locgotno from the .dynamic section and the dyn_symtab entries to
>> compute the got offset.  I can now handle symbols with 0 initial
>> value.
>  Hmm, what you're doing sounds odd to me -- are you trying to gather some 
> sort of statistics about lazy binding calls or what?  There may be 
> functionality to cover this kind of processing already available in ld.so.  
> Also once the program has been loaded the dynamic linker will have already 
> resolved any strong symbol references and you shouldn't be seeing any that 
> still has a null value (that does not apply to weak references that may 
> remain unsatisfied).

Its simple but rather unconventional.  GCL is a lisp system.  It loads
compiled object files at runtime into memory, and executes therefrom.
It can then save the expanded memory image to disk via unexec for
later execution on the same or different machines.  Compiled code can
reference symbols in external shared libraries.  These must be
directed toward some trampoline in the initial final-linked
executable, as otherwise the address loaded might not be valid in a
later execution.  On mips, GCL adds a little stub to load the global
got address from a local got table appended to the .o file, then to
load the contents of this address, and then jump.  GCL ensures that
LD_BIND_NOW is set at runtime via pushing the environment and execve()
on startup.  On other systems, where .plt entries are available, GCL
sets the address to the .plt which takes care of everything.  This is
much cleaner as it requires no little machine-specific assembly.

In the cvs version of GCL, such external calls are made through a C
pointer, which is redirected at startup to the correct address via
dlsym().  A little faster, and makes the loader a little simpler.

We tried to do this via bfd_get_relocated_section_contents, but the
coverage here was very spotty.

>  Also note that if you're doing stuff manually like this, then you may 
> have to take the GOT model used (traditional GOT, xGOT, multi-GOT) into 
> account.

Thankfully thus far this has not proved necessary.  But ia64 and hppa
are the only targets yet unimplemented, so who knows.

Take care,

>> Thanks so much!
>  You are welcome!
>   Maciej

Camm Maguire			     		    camm@maguirefamily.org
"The earth is but one country, and mankind its citizens."  --  Baha'u'llah

Attachment: att
Description: Binary data

Reply to: