programing

gcc 디버그 기호(-g 플래그) vs linker's -rdynamic 옵션

minimums 2023. 9. 20. 20:12
반응형

gcc 디버그 기호(-g 플래그) vs linker's -rdynamic 옵션

glibc 제공backtrace()그리고.backtrace_symbols()실행 중인 프로그램의 스택 추적을 가져옵니다.하지만 이것이 작동하기 위해서는 링커의 프로그램을 사용해야 합니다.-rdynamic깃발을 올리다

사이의 차이점은 무엇입니까?-ggcc vs linker's에 전달된 플래그-rdynamicflag ? 샘플 코드의 경우 출력을 비교하기 위해 redelf를 했습니다.-rdynamic아래에서 더 많은 정보를 만들어 내는 것 같습니다.Symbol table '.dynsym'하지만 추가적인 정보가 무엇인지 잘 모르겠습니다.

설령 내가strip을 이용하여 만들어진 프로그램 바이너리.-rdynamic,backtrace_symbols()일을 계속합니다.

언제strip이진에서 모든 기호를 제거합니다. 왜 그것이 추가된 것을 뒤로하고 있습니까?-rdynamic깃발?

편집 : 아래 매트의 답변을 토대로 한 후속 질문..

당신이 찍은 것과 같은 샘플 코드에 대해 이것이 제가 보는 차이점입니다.-g&-rdynamic

선택의 여지없이..

    Symbol table '.dynsym' contains 4 entries:
       Num:    Value          Size Type    Bind   Vis      Ndx Name
         0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
         1: 0000000000000000   218 FUNC    GLOBAL DEFAULT  UND __libc_start_main@GLIBC_2.2.5 (2)
         2: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _Jv_RegisterClasses
         3: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__

    Symbol table '.symtab' contains 70 entries:
       Num:    Value          Size Type    Bind   Vis      Ndx Name
         0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
         1: 0000000000400200     0 SECTION LOCAL  DEFAULT    1 
         2: 000000000040021c     0 SECTION LOCAL  DEFAULT    2 

와 함께-g더 많은 섹션, 더 많은 항목이 있습니다..symtab테이블 이지만.dynsym지금도 변함이 없습니다..

      [26] .debug_aranges    PROGBITS         0000000000000000  0000095c
           0000000000000030  0000000000000000           0     0     1
      [27] .debug_pubnames   PROGBITS         0000000000000000  0000098c
           0000000000000023  0000000000000000           0     0     1
      [28] .debug_info       PROGBITS         0000000000000000  000009af
           00000000000000a9  0000000000000000           0     0     1
      [29] .debug_abbrev     PROGBITS         0000000000000000  00000a58
           0000000000000047  0000000000000000           0     0     1
      [30] .debug_line       PROGBITS         0000000000000000  00000a9f
           0000000000000038  0000000000000000           0     0     1
      [31] .debug_frame      PROGBITS         0000000000000000  00000ad8
           0000000000000058  0000000000000000           0     0     8
      [32] .debug_loc        PROGBITS         0000000000000000  00000b30
           0000000000000098  0000000000000000           0     0     1

    Symbol table '.dynsym' contains 4 entries:
       Num:    Value          Size Type    Bind   Vis      Ndx Name
         0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
         1: 0000000000000000   218 FUNC    GLOBAL DEFAULT  UND __libc_start_main@GLIBC_2.2.5 (2)
         2: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _Jv_RegisterClasses
         3: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__

    Symbol table '.symtab' contains 77 entries:
       Num:    Value          Size Type    Bind   Vis      Ndx Name
         0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
         1: 0000000000400200     0 SECTION LOCAL  DEFAULT    1 

와 함께-rdynamic추가 디버그 섹션은 없습니다. .symtab 항목은 70개(vanilla gcc 호출과 동일)이지만 그 이상입니다..dynsym항목..

    Symbol table '.dynsym' contains 19 entries:
       Num:    Value          Size Type    Bind   Vis      Ndx Name
         0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
         1: 0000000000000000   218 FUNC    GLOBAL DEFAULT  UND __libc_start_main@GLIBC_2.2.5 (2)
         2: 00000000005008e8     0 OBJECT  GLOBAL DEFAULT  ABS _DYNAMIC
         3: 0000000000400750    57 FUNC    GLOBAL DEFAULT   12 __libc_csu_fini   
         4: 00000000004005e0     0 FUNC    GLOBAL DEFAULT   10 _init
         5: 0000000000400620     0 FUNC    GLOBAL DEFAULT   12 _start
         6: 00000000004006f0    86 FUNC    GLOBAL DEFAULT   12 __libc_csu_init   
         7: 0000000000500ab8     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
         8: 00000000004006de    16 FUNC    GLOBAL DEFAULT   12 main
         9: 0000000000500aa0     0 NOTYPE  WEAK   DEFAULT   23 data_start
        10: 00000000004007c8     0 FUNC    GLOBAL DEFAULT   13 _fini
        11: 00000000004006d8     6 FUNC    GLOBAL DEFAULT   12 foo
        12: 0000000000500ab8     0 NOTYPE  GLOBAL DEFAULT  ABS _edata
        13: 0000000000500a80     0 OBJECT  GLOBAL DEFAULT  ABS _GLOBAL_OFFSET_TABLE_
        14: 0000000000500ac0     0 NOTYPE  GLOBAL DEFAULT  ABS _end
        15: 00000000004007d8     4 OBJECT  GLOBAL DEFAULT   14 _IO_stdin_used
        16: 0000000000500aa0     0 NOTYPE  GLOBAL DEFAULT   23 __data_start
        17: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _Jv_RegisterClasses
        18: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__    

    Symbol table '.symtab' contains 70 entries:
       Num:    Value          Size Type    Bind   Vis      Ndx Name
         0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
         1: 0000000000400200     0 SECTION LOCAL  DEFAULT    1 
         2: 000000000040021c     0 SECTION LOCAL  DEFAULT    2 

이것들이 제가 가진 질문들입니다.

  1. INGDB는 박트레이스를 얻기 위해 당신은 의심할 수 없습니다.그것이 단지 그것과 함께 작동한다면.-g왜 우리가 필요합니까?-rdynamic역추적을 위해 _ symbols이 작동합니까?

  2. 추가된 내용을 다음과.symtab와 함께-g& 에의 추가..dynsym와 함께-rdynamic그들은 완전히 똑같지는 않습니다.둘 중 하나가 다른 하나에 비해 더 나은 디버깅 정보를 제공합니까? FWIW, 생성되는 출력의 크기는 다음과 같습니다: -g > with -rdynamic > with noth option.

  3. .dynsym의 쓰임새는 정확히 무엇입니까?이 바이너리에서 내보낸 심볼이 전부입니까?그렇다면 foo가 .dynsym에 들어가는 이유는 우리가 라이브러리로 코드를 컴파일하고 있지 않기 때문입니다.

  4. 모든 정적 라이브러리를 사용하여 코드를 링크하면 backtrace_symbol이 작동하는 데 -rdynamic이 필요하지 않습니까?

문서에 따르면:

이것은 링커에게 사용된 기호뿐만 아니라 모든 기호를 동적 기호 테이블에 추가하도록 지시합니다.

디버그 기호가 아니라 동적 링커 기호입니다.이들은 다음에 의해 제거되지 않습니다.strip대부분의 경우 실행 파일이 깨지기 때문에 실행 파일의 마지막 링크 단계를 수행하기 위해 런타임 링커에 의해 사용됩니다.

예:

$ cat t.c
void foo() {}
int main() { foo(); return 0; }

없이 컴파일 및 링크하기-rdynamic(그리고 최적화는 분명히 없습니다.)

$ gcc -O0 -o t t.c
$ readelf -s t

Symbol table '.dynsym' contains 3 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@GLIBC_2.2.5 (2)
     2: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__

Symbol table '.symtab' contains 50 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000400270     0 SECTION LOCAL  DEFAULT    1 
....
    27: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS t.c
    28: 0000000000600e14     0 NOTYPE  LOCAL  DEFAULT   18 __init_array_end
    29: 0000000000600e40     0 OBJECT  LOCAL  DEFAULT   21 _DYNAMIC

실행 .symtab모든 것을 걸고하지만 주목할 것은.dynsym없습니다foo그 안에 최소한의 필수품이 들어 있습니다.다에 .backtrace_symbols일하기 위해.코드 주소를 함수 이름과 일치시키기 위해 해당 섹션에 있는 정보에 의존합니다.

합니다.-rdynamic:

$ gcc -O0 -o t t.c -rdynamic
$ readelf -s t

Symbol table '.dynsym' contains 17 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@GLIBC_2.2.5 (2)
     2: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
     3: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _Jv_RegisterClasses
     4: 0000000000601018     0 NOTYPE  GLOBAL DEFAULT  ABS _edata
     5: 0000000000601008     0 NOTYPE  GLOBAL DEFAULT   24 __data_start
     6: 0000000000400734     6 FUNC    GLOBAL DEFAULT   13 foo
     7: 0000000000601028     0 NOTYPE  GLOBAL DEFAULT  ABS _end
     8: 0000000000601008     0 NOTYPE  WEAK   DEFAULT   24 data_start
     9: 0000000000400838     4 OBJECT  GLOBAL DEFAULT   15 _IO_stdin_used
    10: 0000000000400750   136 FUNC    GLOBAL DEFAULT   13 __libc_csu_init
    11: 0000000000400650     0 FUNC    GLOBAL DEFAULT   13 _start
    12: 0000000000601018     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
    13: 000000000040073a    16 FUNC    GLOBAL DEFAULT   13 main
    14: 0000000000400618     0 FUNC    GLOBAL DEFAULT   11 _init
    15: 00000000004007e0     2 FUNC    GLOBAL DEFAULT   13 __libc_csu_fini
    16: 0000000000400828     0 FUNC    GLOBAL DEFAULT   14 _fini

Symbol table '.symtab' contains 50 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000400270     0 SECTION LOCAL  DEFAULT    1 
....
    27: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS t.c
    28: 0000000000600e14     0 NOTYPE  LOCAL  DEFAULT   18 __init_array_end
    29: 0000000000600e40     0 OBJECT  LOCAL  DEFAULT   21 _DYNAMIC

입니다..symtab,그러나 지금.foo는 동적 기호 섹션에 기호가 있습니다(그리고 지금은 여러 개의 다른 기호도 표시됩니다).는을 .backtrace_symbolswork - 이제 함수 이름으로 코드 주소를 매핑하기에 충분한 정보(대부분의 경우)를 가지고 있습니다.

벗기기:

$ strip --strip-all t
$ readelf -s t

Symbol table '.dynsym' contains 17 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@GLIBC_2.2.5 (2)
     2: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
     3: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _Jv_RegisterClasses
     4: 0000000000601018     0 NOTYPE  GLOBAL DEFAULT  ABS _edata
     5: 0000000000601008     0 NOTYPE  GLOBAL DEFAULT   24 __data_start
     6: 0000000000400734     6 FUNC    GLOBAL DEFAULT   13 foo
     7: 0000000000601028     0 NOTYPE  GLOBAL DEFAULT  ABS _end
     8: 0000000000601008     0 NOTYPE  WEAK   DEFAULT   24 data_start
     9: 0000000000400838     4 OBJECT  GLOBAL DEFAULT   15 _IO_stdin_used
    10: 0000000000400750   136 FUNC    GLOBAL DEFAULT   13 __libc_csu_init
    11: 0000000000400650     0 FUNC    GLOBAL DEFAULT   13 _start
    12: 0000000000601018     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
    13: 000000000040073a    16 FUNC    GLOBAL DEFAULT   13 main
    14: 0000000000400618     0 FUNC    GLOBAL DEFAULT   11 _init
    15: 00000000004007e0     2 FUNC    GLOBAL DEFAULT   13 __libc_csu_fini
    16: 0000000000400828     0 FUNC    GLOBAL DEFAULT   14 _fini
$ ./t
$

지금이다.symtab사라졌지만, 동적 기호 테이블은 그대로 있고, 실행 파일은 실행됩니다. 그래서backtrace_symbols여전히 효과가 있습니다.

동적 기호 테이블을 벗깁니다.

$ strip -R .dynsym t
$ ./t
./t: relocation error: ./t: symbol , version GLIBC_2.2.5 not defined in file libc.so.6 with link time reference

... 그리고 부서진 실행 파일을 얻게 됩니다.

에 ..symtab그리고..dynsym사용되는 용도는 다음과 같습니다.내부 ELF 기호 테이블.주의할 점 중 하나는.symtab런타임에 필요하지 않으므로 로더에서 폐기합니다.해당 섹션은 프로세스의 메모리에 남아 있지 않습니다..dynsym, 반면, 이는 런타임 에 필요하므로 프로세스 이미지에 유지됩니다.그래서 그것은 다음과 같은 것들에 이용 가능합니다.backtrace_symbols현재 프로세스에 대한 정보를 자체 내부에서 수집합니다.

그래서 간단히 말해서:

  • 는 에 .strip할 수 없게 만들 수
  • backtrace_symbols어떤 합니다에 속하는지 합니다.
  • backtrace_symbols

그래서 당신이 알아차린 행동입니다.


구체적인 질문은 다음과 같습니다.

  1. gdb디버거 입니다.실행 파일 및 라이브러리의 디버그 정보를 사용하여 관련 정보를 표시합니다.그것은 그것보다 훨씬 더 복잡합니다.backtrace_symbols 파일도 , 합니다.backtrace_symbols실행 파일 이미지에 로드되지 않은 섹션에는 액세스할 수 없습니다.디버그 섹션은 런타임 이미지에 로드되지 않으므로 사용할 수 없습니다.
  2. .dynsym디버깅 섹션이 아닙니다.다이내믹 링커가 사용하는 섹션입니다..symbtab디버깅 섹션도 아니지만 실행 파일(및 라이브러리)에 액세스할 수 있는 디버거에서 사용할 수 있습니다.-rdynamic 디버그 섹션은 생성하지 않고 확장된 동적 심볼 테이블만 생성합니다.실행 가능한 성장성:-rdynamic실행 파일의 심볼 수(및 정렬/padding 고려 사항)에 전적으로 의존합니다.입니다.-g.
  3. 정적으로 연결된 이진 파일을 제외하고 실행 파일은 로드 시 외부 종속성을 해결해야 합니다.하는 것처럼.printfC 라이브러리에서 몇 가지 응용 프로그램 시작 절차를 제공합니다.이러한 다:입니다입니다..dynsym되며인이 exe가를 입니다..dynsym-rdynamic데. 합니다와 수 다른 가 추가됩니다.backtrace_symbols.
  4. backtrace_symbols정적으로 링크하는 경우 함수 이름을 확인하지 않습니다.-rdynamic,.dynsym섹션은 실행 파일로 내보내지 않습니다.obacktrace_symbols코드 주소를 기호에 매핑할 수 없습니다.

언급URL : https://stackoverflow.com/questions/8623884/gcc-debug-symbols-g-flag-vs-linkers-rdynamic-option

반응형