Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UShell Shall NOT Look into symbol.txt for Symbols if Type=NOTYPE but Ndx != UND (UNDefined) #25

Open
hsiehken opened this issue Apr 28, 2023 · 5 comments
Labels
bug Something isn't working

Comments

@hsiehken
Copy link
Collaborator

Following UShell application code:

double getTimestamp()
{
       struct timeval tv;
       gettimeofday(&tv, NULL);
       return (double)tv.tv_sec + ((double)tv.tv_usec) / 1000000;
}

will be translated to

getTimestamp:
.LFB9:
        .cfi_startproc
        subq    $40, %rsp
        .cfi_def_cfa_offset 48
        xorl    %esi, %esi
        movq    %fs:40, %rax
        movq    %rax, 24(%rsp)
        xorl    %eax, %eax
        movq    %rsp, %rdi
        call    gettimeofday@PLT
        pxor    %xmm1, %xmm1
        pxor    %xmm0, %xmm0
        movq    24(%rsp), %rax
        xorq    %fs:40, %rax
        cvtsi2sdq       (%rsp), %xmm1
        cvtsi2sdq       8(%rsp), %xmm0
        divsd   .LC0(%rip), %xmm0
        addsd   %xmm1, %xmm0
        jne     .L5
        addq    $40, %rsp
        .cfi_remember_state
        .cfi_def_cfa_offset 8
        ret
...

.LC0:
        .long   0
        .long   1093567616
        .ident  "GCC: (GNU) 9.5.0"
        .section        .note.GNU-stack,"",@progbits

where .LC0 is a local variable segment containing some arithmetic magic numbers for dividing 1000000.

In the given case, gcc will put such .LC0 segment under 5th segment (.rodata related) and make a symbol table as followings:

Symbol table '.symtab' contains 23 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS tcp-ping.c
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 .text
     3: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT    5 .LC0
     4: 0000000000000000    35 FUNC    GLOBAL DEFAULT    1 getTimestamp
     5: 0000000000000030   300 FUNC    GLOBAL DEFAULT    1 tcpPing
     6: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND lwip_socket
     7: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND inet_addr
     8: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND lwip_connect
     9: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND _GLOBAL_OFFSET_TABLE_
    10: 0000000000000080    26 OBJECT  GLOBAL DEFAULT    3 msgOK
    11: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND sprintf
    12: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND ushell_puts
    13: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND lwip_close
    14: 00000000000000d0    31 OBJECT  GLOBAL DEFAULT    3 msgCreatSocketErr
    15: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND errno
    16: 00000000000000a0    38 OBJECT  GLOBAL DEFAULT    3 msgConnectionErr
    17: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND __stack_chk_fail
    18: 0000000000000160    97 FUNC    GLOBAL DEFAULT    1 main
    19: 0000000000000060    31 OBJECT  GLOBAL DEFAULT    3 msgHello
    20: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND atoi
    21: 0000000000000020    63 OBJECT  GLOBAL DEFAULT    3 msgInvalidUsage
    22: 0000000000000000    15 OBJECT  GLOBAL DEFAULT    3 msgInvalidPort

the entry 3: 0000000000000000 0 NOTYPE LOCAL DEFAULT 5 .LC0 suggests, that .LC0 symbol is exactly existing in the same program at rodata segment, but loader.c:L637 will always try to reallocate it simply due to the NOTYPE the symbol is being marked.

@hsiehken hsiehken added the bug Something isn't working label Apr 28, 2023
@mmisono
Copy link
Member

mmisono commented Apr 28, 2023

@hsiehken Can you push your code into some branch and tell me how to reproduce it?

@mmisono
Copy link
Member

mmisono commented Apr 28, 2023

Related: #11

@mmisono
Copy link
Member

mmisono commented May 2, 2023

maybe this works?

const double A = 1000000;
double getTimestamp()
{
       struct timeval tv;
       gettimeofday(&tv, NULL);
       return (double)tv.tv_sec + ((double)tv.tv_usec) / A;
}

@mmisono
Copy link
Member

mmisono commented May 2, 2023

This is a minimal example:

__attribute__((section(".text")))
int main(int argc, char *argv[])
{
        return (double)argc / 100000;
}

symbol

% readelf -s test
Symbol table '.symtab' contains 5 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS test.c
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 .text
     3: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT    5 .LC0
     4: 0000000000000000    21 FUNC    GLOBAL DEFAULT    1 main

relocation entries

% readelf -r test
Relocation section '.rela.text' at offset 0x168 contains 1 entry:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
00000000000c  000300000002 R_X86_64_PC32     0000000000000000 .LC0 - 4

Relocation section '.rela.eh_frame' at offset 0x180 contains 1 entry:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000000020  000200000002 R_X86_64_PC32     0000000000000000 .text + 0

sections

% readelf -S test
There are 14 section headers, starting at offset 0x218:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .text             PROGBITS         0000000000000000  00000040
       0000000000000015  0000000000000000  AX       0     0     16
  [ 2] .rela.text        RELA             0000000000000000  00000168
       0000000000000018  0000000000000018   I      11     1     8
  [ 3] .data             PROGBITS         0000000000000000  00000055
       0000000000000000  0000000000000000  WA       0     0     1
  [ 4] .bss              NOBITS           0000000000000000  00000055
       0000000000000000  0000000000000000  WA       0     0     1
  [ 5] .rodata.cst8      PROGBITS         0000000000000000  00000058
       0000000000000008  0000000000000008  AM       0     0     8
[...]
  • The constant (100000) is in the .rodata.cst8 section
  • The symbol name is .LC0, whose type is NOTYPE and Bind is LOCLAL

What we need to do is

Possible workaround

  • Can we put the constant in .rodata section (maybe with linker script)? Then maybe current loader just works

@mmisono
Copy link
Member

mmisono commented May 2, 2023

This puts the value in .data section and ushell can load. So we can use this as a workaround.

double A = 100000;

__attribute__((section(".text")))
int main(int argc, char *argv[])
{
        return argc / A;
}
% readelf -r test 
Relocation section '.rela.text' at offset 0x190 contains 1 entry:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000000003  00050000002a R_X86_64_REX_GOTP 0000000000000000 A - 4
% readelf -s test
Symbol table '.symtab' contains 6 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS test.c
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 .text
     3: 0000000000000000    24 FUNC    GLOBAL DEFAULT    1 main
     4: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND _GLOBAL_OFFSET_TABLE_
     5: 0000000000000000     8 OBJECT  GLOBAL DEFAULT    3 A

If a variable is const, we can put the data into .rodata by explicitly specifying it with attributes, but elf symbol still uses .LC0 for relocation. So we need to handle .LC0 symbol resolution in this case.

__attribute__((section(".rodata")))
const double A = 100000;

__attribute__((section(".text")))
int main(int argc, char *argv[])
{
        return argc / A;
}
% readelf -s test 
Symbol table '.symtab' contains 6 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS test.c
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 .text
     3: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT    6 .LC0
     4: 0000000000000000    21 FUNC    GLOBAL DEFAULT    1 main
     5: 0000000000000000     8 OBJECT  GLOBAL DEFAULT    5 A
% readelf -r test 
Relocation section '.rela.text' at offset 0x188 contains 1 entry:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
00000000000c  000300000002 R_X86_64_PC32     0000000000000000 .LC0 - 4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants