linux uml segfault

Hajime Tazaki thehajime at gmail.com
Sun Mar 7 12:22:13 GMT 2021


Sorry that this email is going to be long.  In summary, what Johannes
said is right: what objcopy does is not sufficient, and with ld it
transforms as we expected.

More goes to below.

On Sat, 06 Mar 2021 05:22:19 +0900,
Johannes Berg wrote:
> 
> On Thu, 2021-03-04 at 14:38 +0900, Hajime Tazaki wrote:
> > 
> > objcopy (from binutils) can localize symbols (i.e., objcopy -L
> > sem_init $orig_file $new_file).
> 
> This doesn't seem to be sufficient.
> 
> > It also does renaming symbols.  But
> > not sure this is the ideal solution.
> 
> Even that doesn't seem to actually work/help? I still get libcom_err
> trying to call UML's sem_init, even after doing
>  objcopy --redefine-sym sem_init=uml_sem_init
> 
> 
> > How does UML handle symbol conflicts between userspace code and Linux
> > kernel (like this case sem_init) ?  AFAIK, libnl has a same symbol as
> > Linux kernel (genlmsg_put) and others can possibly do as well.
> 
> I think like I said it just doesn't but since you don't have much
> userspace code linked with UML it never really mattered?
> 
> We only link a 'linux' binary, after all. How does LKL handle this
> though? It should be far more affected?
> 
> 
> Despite the objcopy *not* fixing it, this does seem to:

with slightly old version:
 - objcopy/ld version 2.29.1-23.fc28

I confirmed that objcopy (both --redefine-sym and --localize-symbol)
only changes symbols of .symtab table.  But there is another table,
.dynsym table, which is used to resolve.
So, the original file looks like this:


1) before objcopy (vmlinux)
% readelf -s obj-x86-um/vmlinux |grep -E "sem_init|Symbol table|Num:"
Symbol table '.dynsym' contains 179 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
   129: 0000000060011d38    72 FUNC    GLOBAL DEFAULT    2 sem_init
Symbol table '.symtab' contains 38474 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
 28515: 0000000060011d38    72 FUNC    GLOBAL DEFAULT    2 sem_init
 37798: 00000000601e30d5    62 FUNC    GLOBAL DEFAULT   13 sem_init_ns
 
the result object looks like

2) after objcopy (linux)
% readelf -s obj-x86-um/linux |grep -E "sem_init|Symbol table|Num:"
Symbol table '.dynsym' contains 179 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
   129: 0000000060011d38    72 FUNC    GLOBAL DEFAULT    2 sem_init
Symbol table '.symtab' contains 38474 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
 28455: 0000000060011d38    72 FUNC    LOCAL  DEFAULT    2 sem_init
 37798: 00000000601e30d5    62 FUNC    GLOBAL DEFAULT   13 sem_init_ns

Only .symtab symbol table is changed to local while .dynsym table is
not changed.  So, sem_init call from libcom_err.so still can resolve
the Linux symbol.


On the other hand, ld --version script solution does as we wish.

3) localized with ld
% readelf -s obj-x86-um/linux G -E "sem_init|Symbol table|Num:" 
Symbol table '.dynsym' contains 142 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
Symbol table '.symtab' contains 38474 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
 28512: 0000000060011d38    72 FUNC    LOCAL  DEFAULT    2 sem_init
 37669: 00000000601e2b45    62 FUNC    LOCAL  DEFAULT   13 sem_init_ns

Only .symtab table is generated for the sem_init symbol and it's localized.


Because the way to build is different from what UML currently does,
LKL (and UML binaries) do not have this issue, with a quick check.

LKL applies objcopy before generating intermediate file (linux.o), and
the symbols of the final binary (linux) are localized and have no
.dynsym entries, thus no issue in this case.

refs:
https://stackoverflow.com/questions/54332797/binding-failure-with-objcopy-redefine-syms
https://sourceware.org/legacy-ml/binutils/2019-01/msg00254.html


-- Hajime



More information about the linux-um mailing list