`
u0fly
  • 浏览: 2798 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

程序员的自我修养---读书笔记

阅读更多
二.

1.预处理(preprocessing)->编译(compilation)->汇编(assembly)->链接(linking)

2.预编译 gcc -E hello.c -o hello.i

   Hello.i中的内容:

 

   # 1 "Hello.c"

# 1 "<built-in>"

# 1 "<command-line>"

# 1 "Hello.c"

# 1 "/usr/include/stdio.h" 1 3 4

# 28 "/usr/include/stdio.h" 3 4

# 1 "/usr/include/features.h" 1 3 4

# 313 "/usr/include/features.h" 3 4

# 1 "/usr/include/bits/predefs.h" 1 3 4

# 314 "/usr/include/features.h" 2 3 4

# 346 "/usr/include/features.h" 3 4

# 1 "/usr/include/sys/cdefs.h" 1 3 4

# 353 "/usr/include/sys/cdefs.h" 3 4

# 1 "/usr/include/bits/wordsize.h" 1 3 4

# 354 "/usr/include/sys/cdefs.h" 2 3 4

# 347 "/usr/include/features.h" 2 3 4

# 378 "/usr/include/features.h" 3 4

# 1 "/usr/include/gnu/stubs.h" 1 3 4







# 1 "/usr/include/bits/wordsize.h" 1 3 4

# 5 "/usr/include/gnu/stubs.h" 2 3 4





# 1 "/usr/include/gnu/stubs-32.h" 1 3 4

# 8 "/usr/include/gnu/stubs.h" 2 3 4

# 379 "/usr/include/features.h" 2 3 4

# 29 "/usr/include/stdio.h" 2 3 4











# 1 "/usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h" 1 3 4

# 211 "/usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h" 3 4

typedef unsigned int size_t;

# 35 "/usr/include/stdio.h" 2 3 4



# 1 "/usr/include/bits/types.h" 1 3 4

# 28 "/usr/include/bits/types.h" 3 4

# 1 "/usr/include/bits/wordsize.h" 1 3 4

# 29 "/usr/include/bits/types.h" 2 3 4





typedef unsigned char __u_char;

typedef unsigned short int __u_short;

typedef unsigned int __u_int;

typedef unsigned long int __u_long;





typedef signed char __int8_t;

typedef unsigned char __uint8_t;

typedef signed short int __int16_t;

typedef unsigned short int __uint16_t;

typedef signed int __int32_t;

typedef unsigned int __uint32_t;









__extension__ typedef signed long long int __int64_t;

__extension__ typedef unsigned long long int __uint64_t;















__extension__ typedef long long int __quad_t;

__extension__ typedef unsigned long long int __u_quad_t;

# 131 "/usr/include/bits/types.h" 3 4

# 1 "/usr/include/bits/typesizes.h" 1 3 4

# 132 "/usr/include/bits/types.h" 2 3 4





__extension__ typedef __u_quad_t __dev_t;

__extension__ typedef unsigned int __uid_t;

__extension__ typedef unsigned int __gid_t;

__extension__ typedef unsigned long int __ino_t;

__extension__ typedef __u_quad_t __ino64_t;

__extension__ typedef unsigned int __mode_t;

__extension__ typedef unsigned int __nlink_t;

__extension__ typedef long int __off_t;

__extension__ typedef __quad_t __off64_t;

__extension__ typedef int __pid_t;

__extension__ typedef struct { int __val[2]; } __fsid_t;

__extension__ typedef long int __clock_t;

__extension__ typedef unsigned long int __rlim_t;

__extension__ typedef __u_quad_t __rlim64_t;

__extension__ typedef unsigned int __id_t;

__extension__ typedef long int __time_t;

__extension__ typedef unsigned int __useconds_t;

__extension__ typedef long int __suseconds_t;



__extension__ typedef int __daddr_t;

__extension__ typedef long int __swblk_t;

__extension__ typedef int __key_t;





__extension__ typedef int __clockid_t;





__extension__ typedef void * __timer_t;





__extension__ typedef long int __blksize_t;









__extension__ typedef long int __blkcnt_t;

__extension__ typedef __quad_t __blkcnt64_t;





__extension__ typedef unsigned long int __fsblkcnt_t;

__extension__ typedef __u_quad_t __fsblkcnt64_t;





__extension__ typedef unsigned long int __fsfilcnt_t;

__extension__ typedef __u_quad_t __fsfilcnt64_t;



__extension__ typedef int __ssize_t;







typedef __off64_t __loff_t;

typedef __quad_t *__qaddr_t;

typedef char *__caddr_t;





__extension__ typedef int __intptr_t;





__extension__ typedef unsigned int __socklen_t;

# 37 "/usr/include/stdio.h" 2 3 4

# 45 "/usr/include/stdio.h" 3 4

struct _IO_FILE;







typedef struct _IO_FILE FILE;











# 65 "/usr/include/stdio.h" 3 4

typedef struct _IO_FILE __FILE;

# 75 "/usr/include/stdio.h" 3 4

# 1 "/usr/include/libio.h" 1 3 4

# 32 "/usr/include/libio.h" 3 4

# 1 "/usr/include/_G_config.h" 1 3 4

# 15 "/usr/include/_G_config.h" 3 4

# 1 "/usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h" 1 3 4

# 16 "/usr/include/_G_config.h" 2 3 4









# 1 "/usr/include/wchar.h" 1 3 4

# 83 "/usr/include/wchar.h" 3 4

typedef struct

{

  int __count;

  union

  {



    unsigned int __wch;







    char __wchb[4];

  } __value;

} __mbstate_t;

# 21 "/usr/include/_G_config.h" 2 3 4



typedef struct

{

  __off_t __pos;

  __mbstate_t __state;

} _G_fpos_t;

typedef struct

{

  __off64_t __pos;

  __mbstate_t __state;

} _G_fpos64_t;

# 53 "/usr/include/_G_config.h" 3 4

typedef int _G_int16_t __attribute__ ((__mode__ (__HI__)));

typedef int _G_int32_t __attribute__ ((__mode__ (__SI__)));

typedef unsigned int _G_uint16_t __attribute__ ((__mode__ (__HI__)));

typedef unsigned int _G_uint32_t __attribute__ ((__mode__ (__SI__)));

# 33 "/usr/include/libio.h" 2 3 4

# 53 "/usr/include/libio.h" 3 4

# 1 "/usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h" 1 3 4

# 40 "/usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h" 3 4

typedef __builtin_va_list __gnuc_va_list;

# 54 "/usr/include/libio.h" 2 3 4

# 170 "/usr/include/libio.h" 3 4

struct _IO_jump_t; struct _IO_FILE;

# 180 "/usr/include/libio.h" 3 4

typedef void _IO_lock_t;











struct _IO_marker {

  struct _IO_marker *_next;

  struct _IO_FILE *_sbuf;







  int _pos;

# 203 "/usr/include/libio.h" 3 4

};





enum __codecvt_result

{

  __codecvt_ok,

  __codecvt_partial,

  __codecvt_error,

  __codecvt_noconv

};

# 271 "/usr/include/libio.h" 3 4

struct _IO_FILE {

  int _flags;









  char* _IO_read_ptr;

  char* _IO_read_end;

  char* _IO_read_base;

  char* _IO_write_base;

  char* _IO_write_ptr;

  char* _IO_write_end;

  char* _IO_buf_base;

  char* _IO_buf_end;



  char *_IO_save_base;

  char *_IO_backup_base;

  char *_IO_save_end;



  struct _IO_marker *_markers;



  struct _IO_FILE *_chain;



  int _fileno;







  int _flags2;



  __off_t _old_offset;







  unsigned short _cur_column;

  signed char _vtable_offset;

  char _shortbuf[1];







  _IO_lock_t *_lock;

# 319 "/usr/include/libio.h" 3 4

  __off64_t _offset;

# 328 "/usr/include/libio.h" 3 4

  void *__pad1;

  void *__pad2;

  void *__pad3;

  void *__pad4;

  size_t __pad5;



  int _mode;



  char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)];



};





typedef struct _IO_FILE _IO_FILE;





struct _IO_FILE_plus;



extern struct _IO_FILE_plus _IO_2_1_stdin_;

extern struct _IO_FILE_plus _IO_2_1_stdout_;

extern struct _IO_FILE_plus _IO_2_1_stderr_;

# 364 "/usr/include/libio.h" 3 4

typedef __ssize_t __io_read_fn (void *__cookie, char *__buf, size_t __nbytes);















typedef __ssize_t __io_write_fn (void *__cookie, __const char *__buf,

     size_t __n);















typedef int __io_seek_fn (void *__cookie, __off64_t *__pos, int __w);





typedef int __io_close_fn (void *__cookie);

# 416 "/usr/include/libio.h" 3 4

extern int __underflow (_IO_FILE *);

extern int __uflow (_IO_FILE *);

extern int __overflow (_IO_FILE *, int);

# 460 "/usr/include/libio.h" 3 4

extern int _IO_getc (_IO_FILE *__fp);

extern int _IO_putc (int __c, _IO_FILE *__fp);

extern int _IO_feof (_IO_FILE *__fp) __attribute__ ((__nothrow__));

extern int _IO_ferror (_IO_FILE *__fp) __attribute__ ((__nothrow__));



extern int _IO_peekc_locked (_IO_FILE *__fp);











extern void _IO_flockfile (_IO_FILE *) __attribute__ ((__nothrow__));

extern void _IO_funlockfile (_IO_FILE *) __attribute__ ((__nothrow__));

extern int _IO_ftrylockfile (_IO_FILE *) __attribute__ ((__nothrow__));

# 490 "/usr/include/libio.h" 3 4

extern int _IO_vfscanf (_IO_FILE * __restrict, const char * __restrict,

   __gnuc_va_list, int *__restrict);

extern int _IO_vfprintf (_IO_FILE *__restrict, const char *__restrict,

    __gnuc_va_list);

extern __ssize_t _IO_padn (_IO_FILE *, int, __ssize_t);

extern size_t _IO_sgetn (_IO_FILE *, void *, size_t);



extern __off64_t _IO_seekoff (_IO_FILE *, __off64_t, int, int);

extern __off64_t _IO_seekpos (_IO_FILE *, __off64_t, int);



extern void _IO_free_backup_area (_IO_FILE *) __attribute__ ((__nothrow__));

# 76 "/usr/include/stdio.h" 2 3 4

# 89 "/usr/include/stdio.h" 3 4





typedef _G_fpos_t fpos_t;









# 141 "/usr/include/stdio.h" 3 4

# 1 "/usr/include/bits/stdio_lim.h" 1 3 4

# 142 "/usr/include/stdio.h" 2 3 4







extern struct _IO_FILE *stdin;

extern struct _IO_FILE *stdout;

extern struct _IO_FILE *stderr;















extern int remove (__const char *__filename) __attribute__ ((__nothrow__));



extern int rename (__const char *__old, __const char *__new) __attribute__ ((__nothrow__));









extern int renameat (int __oldfd, __const char *__old, int __newfd,

       __const char *__new) __attribute__ ((__nothrow__));

















extern FILE *tmpfile (void) ;

# 186 "/usr/include/stdio.h" 3 4

extern char *tmpnam (char *__s) __attribute__ ((__nothrow__)) ;











extern char *tmpnam_r (char *__s) __attribute__ ((__nothrow__)) ;

# 204 "/usr/include/stdio.h" 3 4

extern char *tempnam (__const char *__dir, __const char *__pfx)

     __attribute__ ((__nothrow__)) __attribute__ ((__malloc__)) ;

















extern int fclose (FILE *__stream);









extern int fflush (FILE *__stream);



# 229 "/usr/include/stdio.h" 3 4

extern int fflush_unlocked (FILE *__stream);

# 243 "/usr/include/stdio.h" 3 4













extern FILE *fopen (__const char *__restrict __filename,

      __const char *__restrict __modes) ;









extern FILE *freopen (__const char *__restrict __filename,

        __const char *__restrict __modes,

        FILE *__restrict __stream) ;

# 272 "/usr/include/stdio.h" 3 4



# 283 "/usr/include/stdio.h" 3 4

extern FILE *fdopen (int __fd, __const char *__modes) __attribute__ ((__nothrow__)) ;

# 296 "/usr/include/stdio.h" 3 4

extern FILE *fmemopen (void *__s, size_t __len, __const char *__modes)

  __attribute__ ((__nothrow__)) ;









extern FILE *open_memstream (char **__bufloc, size_t *__sizeloc) __attribute__ ((__nothrow__)) ;













extern void setbuf (FILE *__restrict __stream, char *__restrict __buf) __attribute__ ((__nothrow__));







extern int setvbuf (FILE *__restrict __stream, char *__restrict __buf,

      int __modes, size_t __n) __attribute__ ((__nothrow__));











extern void setbuffer (FILE *__restrict __stream, char *__restrict __buf,

         size_t __size) __attribute__ ((__nothrow__));





extern void setlinebuf (FILE *__stream) __attribute__ ((__nothrow__));

















extern int fprintf (FILE *__restrict __stream,

      __const char *__restrict __format, ...);









extern int printf (__const char *__restrict __format, ...);



extern int sprintf (char *__restrict __s,

      __const char *__restrict __format, ...) __attribute__ ((__nothrow__));











extern int vfprintf (FILE *__restrict __s, __const char *__restrict __format,

       __gnuc_va_list __arg);









extern int vprintf (__const char *__restrict __format, __gnuc_va_list __arg);



extern int vsprintf (char *__restrict __s, __const char *__restrict __format,

       __gnuc_va_list __arg) __attribute__ ((__nothrow__));











extern int snprintf (char *__restrict __s, size_t __maxlen,

       __const char *__restrict __format, ...)

     __attribute__ ((__nothrow__)) __attribute__ ((__format__ (__printf__, 3, 4)));



extern int vsnprintf (char *__restrict __s, size_t __maxlen,

        __const char *__restrict __format, __gnuc_va_list __arg)

     __attribute__ ((__nothrow__)) __attribute__ ((__format__ (__printf__, 3, 0)));



# 394 "/usr/include/stdio.h" 3 4

extern int vdprintf (int __fd, __const char *__restrict __fmt,

       __gnuc_va_list __arg)

     __attribute__ ((__format__ (__printf__, 2, 0)));

extern int dprintf (int __fd, __const char *__restrict __fmt, ...)

     __attribute__ ((__format__ (__printf__, 2, 3)));

















extern int fscanf (FILE *__restrict __stream,

     __const char *__restrict __format, ...) ;









extern int scanf (__const char *__restrict __format, ...) ;



extern int sscanf (__const char *__restrict __s,

     __const char *__restrict __format, ...) __attribute__ ((__nothrow__));

# 425 "/usr/include/stdio.h" 3 4

extern int fscanf (FILE *__restrict __stream, __const char *__restrict __format, ...) __asm__ ("" "__isoc99_fscanf") ;





extern int scanf (__const char *__restrict __format, ...) __asm__ ("" "__isoc99_scanf") ;



extern int sscanf (__const char *__restrict __s, __const char *__restrict __format, ...) __asm__ ("" "__isoc99_sscanf") __attribute__ ((__nothrow__));

# 445 "/usr/include/stdio.h" 3 4

















extern int vfscanf (FILE *__restrict __s, __const char *__restrict __format,

      __gnuc_va_list __arg)

     __attribute__ ((__format__ (__scanf__, 2, 0))) ;











extern int vscanf (__const char *__restrict __format, __gnuc_va_list __arg)

     __attribute__ ((__format__ (__scanf__, 1, 0))) ;





extern int vsscanf (__const char *__restrict __s,

      __const char *__restrict __format, __gnuc_va_list __arg)

     __attribute__ ((__nothrow__)) __attribute__ ((__format__ (__scanf__, 2, 0)));

# 476 "/usr/include/stdio.h" 3 4

extern int vfscanf (FILE *__restrict __s, __const char *__restrict __format, __gnuc_va_list __arg) __asm__ ("" "__isoc99_vfscanf")







     __attribute__ ((__format__ (__scanf__, 2, 0))) ;

extern int vscanf (__const char *__restrict __format, __gnuc_va_list __arg) __asm__ ("" "__isoc99_vscanf")



     __attribute__ ((__format__ (__scanf__, 1, 0))) ;

extern int vsscanf (__const char *__restrict __s, __const char *__restrict __format, __gnuc_va_list __arg) __asm__ ("" "__isoc99_vsscanf")







     __attribute__ ((__nothrow__)) __attribute__ ((__format__ (__scanf__, 2, 0)));

# 504 "/usr/include/stdio.h" 3 4



















extern int fgetc (FILE *__stream);

extern int getc (FILE *__stream);











extern int getchar (void);



# 532 "/usr/include/stdio.h" 3 4

extern int getc_unlocked (FILE *__stream);

extern int getchar_unlocked (void);

# 543 "/usr/include/stdio.h" 3 4

extern int fgetc_unlocked (FILE *__stream);























extern int fputc (int __c, FILE *__stream);

extern int putc (int __c, FILE *__stream);











extern int putchar (int __c);



# 576 "/usr/include/stdio.h" 3 4

extern int fputc_unlocked (int __c, FILE *__stream);















extern int putc_unlocked (int __c, FILE *__stream);

extern int putchar_unlocked (int __c);













extern int getw (FILE *__stream);





extern int putw (int __w, FILE *__stream);

















extern char *fgets (char *__restrict __s, int __n, FILE *__restrict __stream)

     ;













extern char *gets (char *__s) ;



# 638 "/usr/include/stdio.h" 3 4

extern __ssize_t __getdelim (char **__restrict __lineptr,

          size_t *__restrict __n, int __delimiter,

          FILE *__restrict __stream) ;

extern __ssize_t getdelim (char **__restrict __lineptr,

        size_t *__restrict __n, int __delimiter,

        FILE *__restrict __stream) ;















extern __ssize_t getline (char **__restrict __lineptr,

       size_t *__restrict __n,

       FILE *__restrict __stream) ;

















extern int fputs (__const char *__restrict __s, FILE *__restrict __stream);











extern int puts (__const char *__s);













extern int ungetc (int __c, FILE *__stream);













extern size_t fread (void *__restrict __ptr, size_t __size,

       size_t __n, FILE *__restrict __stream) ;









extern size_t fwrite (__const void *__restrict __ptr, size_t __size,

        size_t __n, FILE *__restrict __s);



# 710 "/usr/include/stdio.h" 3 4

extern size_t fread_unlocked (void *__restrict __ptr, size_t __size,

         size_t __n, FILE *__restrict __stream) ;

extern size_t fwrite_unlocked (__const void *__restrict __ptr, size_t __size,

          size_t __n, FILE *__restrict __stream);

















extern int fseek (FILE *__stream, long int __off, int __whence);









extern long int ftell (FILE *__stream) ;









extern void rewind (FILE *__stream);



# 746 "/usr/include/stdio.h" 3 4

extern int fseeko (FILE *__stream, __off_t __off, int __whence);









extern __off_t ftello (FILE *__stream) ;

# 765 "/usr/include/stdio.h" 3 4













extern int fgetpos (FILE *__restrict __stream, fpos_t *__restrict __pos);









extern int fsetpos (FILE *__stream, __const fpos_t *__pos);

# 788 "/usr/include/stdio.h" 3 4



# 797 "/usr/include/stdio.h" 3 4





extern void clearerr (FILE *__stream) __attribute__ ((__nothrow__));



extern int feof (FILE *__stream) __attribute__ ((__nothrow__)) ;



extern int ferror (FILE *__stream) __attribute__ ((__nothrow__)) ;









extern void clearerr_unlocked (FILE *__stream) __attribute__ ((__nothrow__));

extern int feof_unlocked (FILE *__stream) __attribute__ ((__nothrow__)) ;

extern int ferror_unlocked (FILE *__stream) __attribute__ ((__nothrow__)) ;

















extern void perror (__const char *__s);













# 1 "/usr/include/bits/sys_errlist.h" 1 3 4

# 27 "/usr/include/bits/sys_errlist.h" 3 4

extern int sys_nerr;

extern __const char *__const sys_errlist[];

# 827 "/usr/include/stdio.h" 2 3 4









extern int fileno (FILE *__stream) __attribute__ ((__nothrow__)) ;









extern int fileno_unlocked (FILE *__stream) __attribute__ ((__nothrow__)) ;

# 846 "/usr/include/stdio.h" 3 4

extern FILE *popen (__const char *__command, __const char *__modes) ;











extern int pclose (FILE *__stream);











extern char *ctermid (char *__s) __attribute__ ((__nothrow__));

# 886 "/usr/include/stdio.h" 3 4

extern void flockfile (FILE *__stream) __attribute__ ((__nothrow__));







extern int ftrylockfile (FILE *__stream) __attribute__ ((__nothrow__)) ;





extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__));

# 916 "/usr/include/stdio.h" 3 4



# 2 "Hello.c" 2

int main (int argc, char **argv)

{

printf("Hello World!\n");

return 0;

}

3.编译    gcc -S hello.i -o hello.s

   Hello.s 中的内容:

   .file "Hello.c"

   .section .rodata

.LC0:

   .string "Hello World!"

   .text

.globl main

   .type main, @function

main:

   pushl %ebp

   movl  %esp, %ebp

   andl  $-16, %esp

   subl  $16, %esp

   movl  $.LC0, (%esp)

   call  puts

   movl  $0, %eax

   leave

   ret

   .size main, .-main

   .ident  "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"

   .section .note.GNU-stack,"",@progbits



4.汇编

   gcc -c hello.s -o hello.o

或    as hello.s -o hello.o



5.链接

   编译器:扫描->语法分析->语义分析->源代码优化->代码生成->目标代码优化



*【有限状态机】算法

* lex 词法分析器

语法分析器(Grammar Parser) ->产生语法树(Syntax Tree)就是以表达式为节点的树

*上下文无关语法(Context-free Grammar)





语法分析工具:yacc(Yet Another Compiler Compiler)



语义分析:

语义分析器(Semantic Analyzer)



静态语义

动态语义







中间语言生成:

源代码优化器(Source Code Optimizer)





中间代码可以将编译器分为 前端和 后端:



模块之间的通信:(1)函数调用(2)变量的访问

两者都可以归结为 模块间符号的引用



2.4 静态链接

ELF文件类型:可重定位文件,可执行文件,共享目标文件,核心转储文件

Relocatable File

Executable File

Shared Object File

Core Dump File



SimpleSection.c



int printf(const char* format, ...);

int global_init_var = 84;

int global_uninit_var;



void func1( int i )

{

   printf("%d\n", i);

}



int main(void)

{

   static int static_var = 85;

   static int static_var2;



   int a = 1;

   int b;



   func1( static_var + static_var2 + a + b);



   return a;

}



gcc -c SimpleSection.c



objdump -h SimpleSection.o 用来查看object内部的结构



* readelf 是专门针对ELF格式文件的解析器

* size命令可以用来查看ELF文件的代码段、数据段和BSS段的长度



ELF文件格式结构:

***

ELF Header

***

.text

***

.data

***

.bss

***

...other sections

***

Section header table

***

String Tables

Symbol Tables

....



整个链接过程正是基于符号来完成的



* nm 命令 可以用来查看*.o中的符号

$ nm SimpleSection.o





*函数签名(Function Signature)



*c++filt 可以用来解析被修饰过的名称

$ c++filt _ZN1N1C4funcEi





#ifdef __cplusplus

extern “C”{

#endif



void *memset (void *, int, size_t);

#ifdef __cplusplus

}

#endif



*弱符号 弱引用 强符号 强引用



如果一个程序被设计成可以支持单线程或多线程的模式,就可以通过弱引用的方法来判断当前的程序是链接到了单线程的Glibc库还是多线程的Glibc库(是否在编译时有-lpthread选项)



#include <stdio.h>

#include <pthread.h>



int pthread_create(

      pthread_t *,

      const pthread_attr_t*,

      void * (*)(void*),

      void *)

__attribute__ ((weak));



int main(){

   if(pthread_create){

      printf("This is multi-thread version\n");

      // run the multi-thread version

      // main_multi_thread()

   }else{

      printf("This is single-thread version\n");

   }



}



$ gcc pthread.c -o pt

$ gcc pthread.c -lpthread -o pt





*在linux下我们可以用 strip 命令去掉调试信息!



四.静态链接

4.1 空间与地址分配





4.2符号解析与重定位

* objdump -d a.o 可以查看a.o的代码反汇编结果

* objdump -r a.o 可以查看a.o的重定位表



4.3COMMON块

4.4C++相关问题

*函数级别链接

4.5静态库链接

* ar -t libc.a  ar工具查看静态库



e.g:



$ gcc -c -fno-builtin hello.c

//默认情况GCC会自作聪明的将”printf”替换成“puts”以提高运行速度

$ ar -x libc.a

//将libc.a 中的所有目标文件解压到当前目录

$ld hello.o printf.o

//链接却失败了!!!!!原因是缺少2个外部符号的定义





$ gcc  -static  --verbose -fno-builtin hello.c



--verbose 可以将编译链接的中间所有过程打印出来



cc1 GCC的c语言编译器

as GNU的汇编器

collect2 ld连接器的一个包装



4.6链接库控制



*.c



char * str = "Hello World!\n";



void print()

{

   asm( "movl $13, %%edx \n\t"

        "movl %0, %%ecx \n\t"

        "movl $0, %%ebx \n\t"

        "movl $4, %%eax \n\t"

        "int $0x80 \n\t"

        ::"r"(str):"edx","ecx","ebx");

}

void exit()

{

   asm("movl $42, %ebx \n\t"

        "movl $1, %eax \n\t"

        "int $0x80 \n\t");

}



void nomain()

{

   print();

   exit();

}



*.lds



ENTRY(nomain)

   SECTIONS

{

   . = 0x08048000 + SIZEOF_HEADERS;

tinytext : { *(.text) *(.data) *(.rodata)}

         /DISCARD/ : {*(.comment)}

}



gcc -c -fno-builtin *.c



ld -static -T *.lds -o *.c *.o







4.7BFD库

本章小结



六.可执行文件的装载和执行



*页映射

6.3.1 进程的建立

(1)创建虚拟地址空间

(2)读取可执行文件头,并且建立虚拟空间与可执行文件的映射关系

*虚拟内存区域 (VMA Virtual Memory Area)

(3)将CPU指令寄存器设置成可执行文件的入口,启动执行



段的权限:

(1)以代码段为代表的权限为可读可执行的段

(2)以数据段和BSS段为代表的权限为可读可写的段

(3)以只读数据段为代表的权限为只读的段



对于权限相同的段,我们可以合并映射(可以减少页面的碎片,节省内存空间)



从section角度看ELF文件就是链接视图(Linking View)

从segment的角度看ELF文件就是执行视图(Execution View)



fly@Baby-o_o:~/Code/HelloWorld$ readelf -S SectionMapping.elf

There are 27 section headers, starting at offset 0x7d84c:



Section Headers:

  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al

  [ 0]                   NULL            00000000 000000 000000 00      0   0  0

  [ 1] .note.ABI-tag     NOTE            080480f4 0000f4 000020 00   A  0   0  4

  [ 2] .note.gnu.build-i NOTE            08048114 000114 000024 00   A  0   0  4

  [ 3] .init             PROGBITS        08048138 000138 000030 00  AX  0   0  4

  [ 4] .text             PROGBITS        08048170 000170 05eb3c 00  AX  0   0 16

  [ 5] __libc_freeres_fn PROGBITS        080a6cb0 05ecb0 000b57 00  AX  0   0 16

  [ 6] .fini             PROGBITS        080a7808 05f808 00001c 00  AX  0   0  4

  [ 7] .rodata           PROGBITS        080a7840 05f840 018650 00   A  0   0 32

  [ 8] __libc_subfreeres PROGBITS        080bfe90 077e90 000030 00   A  0   0  4

  [ 9] __libc_atexit     PROGBITS        080bfec0 077ec0 000004 00   A  0   0  4

  [10] .eh_frame         PROGBITS        080bfec4 077ec4 004dc0 00   A  0   0  4

  [11] .gcc_except_table PROGBITS        080c4c84 07cc84 00011a 00   A  0   0  1

  [12] .tdata            PROGBITS        080c5f98 07cf98 000010 00 WAT  0   0  4

  [13] .tbss             NOBITS          080c5fa8 07cfa8 000018 00 WAT  0   0  4

  [14] .ctors            PROGBITS        080c5fa8 07cfa8 000008 00  WA  0   0  4

  [15] .dtors            PROGBITS        080c5fb0 07cfb0 00000c 00  WA  0   0  4

  [16] .jcr              PROGBITS        080c5fbc 07cfbc 000004 00  WA  0   0  4

  [17] .data.rel.ro      PROGBITS        080c5fc0 07cfc0 00002c 00  WA  0   0  4

  [18] .got              PROGBITS        080c5fec 07cfec 000008 04  WA  0   0  4

  [19] .got.plt          PROGBITS        080c5ff4 07cff4 00000c 04  WA  0   0  4

  [20] .data             PROGBITS        080c6000 07d000 000720 00  WA  0   0 32

  [21] .bss              NOBITS          080c6720 07d720 001b5c 00  WA  0   0 32

  [22] __libc_freeres_pt NOBITS          080c827c 07d720 000018 00  WA  0   0  4

  [23] .comment          PROGBITS        00000000 07d720 000023 01  MS  0   0  1

  [24] .shstrtab         STRTAB          00000000 07d743 000107 00      0   0  1

  [25] .symtab           SYMTAB          00000000 07dc84 008200 10     26 967  4

  [26] .strtab           STRTAB          00000000 085e84 007397 00      0   0  1

Key to Flags:

  W (write), A (alloc), X (execute), M (merge), S (strings)

  I (info), L (link order), G (group), x (unknown)

  O (extra OS processing required) o (OS specific), p (processor specific)



fly@Baby-o_o:~/Code/HelloWorld$ readelf -l SectionMapping.elf



Elf file type is EXEC (Executable file)

Entry point 0x8048170

There are 6 program headers, starting at offset 52



Program Headers:

  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align

  LOAD           0x000000 0x08048000 0x08048000 0x7cd9e 0x7cd9e R E 0x1000

  LOAD           0x07cf98 0x080c5f98 0x080c5f98 0x00788 0x022fc RW  0x1000

  NOTE           0x0000f4 0x080480f4 0x080480f4 0x00044 0x00044 R   0x4

  TLS            0x07cf98 0x080c5f98 0x080c5f98 0x00010 0x00028 R   0x4

  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x4

  GNU_RELRO      0x07cf98 0x080c5f98 0x080c5f98 0x00068 0x00068 R   0x1



Section to Segment mapping:

  Segment Sections...

   00     .note.ABI-tag .note.gnu.build-id .init .text __libc_freeres_fn .fini .rodata __libc_subfreeres __libc_atexit .eh_frame .gcc_except_table

   01     .tdata .ctors .dtors .jcr .data.rel.ro .got .got.plt .data .bss __libc_freeres_ptrs

   02     .note.ABI-tag .note.gnu.build-id

   03     .tdata .tbss

   04   

   05     .tdata .ctors .dtors .jcr .data.rel.ro .got .got.plt





我们可以通过查看 “/proc”来查看进程的虚拟空间分布:

$ ./SectionMapping.elf &

[1]21963

$cat /proc/21963/maps



fly@Baby-o_o:~/Code/HelloWorld$ ./SectionMapping.elf &

[1] 3869

fly@Baby-o_o:~/Code/HelloWorld$ cat /proc/3869/maps

08048000-080c5000 r-xp 00000000 08:01 18874525   /home/fly/Code/HelloWorld/SectionMapping.elf

080c5000-080c7000 rwxp 0007c000 08:01 18874525   /home/fly/Code/HelloWorld/SectionMapping.elf

080c7000-080c9000 rwxp 00000000 00:00 0

08ee4000-08f06000 rwxp 00000000 00:00 0          [heap]

b7746000-b7747000 r-xp 00000000 00:00 0          [vdso]

bfc5b000-bfc70000 rw-p 00000000 00:00 0          [stack]



*匿名虚拟内存区域(Anonymous Virtual Memory  Area)



p192

6.5 linux内核装载ELF过程简介

(1)用户层面:bash进程->fork()->execve()->执行elf->bash进程等待其结束

execve()被定义在unistd.h 原型:

int execve(const char *filename, char *const argv[], char *const envp[]);



*p174



七.动态链接



静态库的缺点:

(1)浪费内存空间,不同的程序调用相同的静态库,会在内存中存在两个相同的静态库的副本

(2)影响程序的更新、部署、和发布

一旦有一个模块需要更新,整个程序就要重新链接,发布给客户



为了解决上述静态库的缺点,动态库应运而生,把链接这个工程推迟到了运行时进行(动态链接 Dynamic Linking 的基本思想)



这样做的好处不仅仅是节省内存,还可以减少物理页面的换入换出,增加CPU缓存的命中率(因为不同进程间的数据和指令访问都集中在了同一个共享模块上)



缺点:当新旧模块接口不兼容的时候,导致原有的程序无法运行!!!



*延迟绑定



Example: SimpleDynamicalLinking



a.c

#include "Lib.h"



int main(){

   foobar(1);

   return 0;

}



b.c



#include "Lib.h"



int main(){

   foobar(2);

   return 0;

}



Lib.c

#include <stdio.h>



void foobar(int i){



   printf("Printing from Lib.so %d\n", i);

}



Lib.h



#ifndef LIB_H

#define LIB_H



void foobar(int i);



#endif



$ gcc -fPIC -shared -o Lib.so Lib.c

$ gcc -o a a.c ./Lib.so







Libc -> [Compiler] -> Lib.o -> [Linker] <- [C Runtime Library]

                            |

                            \/

                            Lib.so

                            |

                            \/

    a.c -> [Compiler] -> a.o -> [Linker] -> a





7.3 地址无关代码



静态库 使用编译时重定位

动态库 使用装载时重定位



如果上面只使用 -shared 参数, 则输出的共享对象 就是使用的 装载时重定位的方法

但是 这样虽然可以解决动态模块中有绝对地址引用,但是缺点是:指令部分无法在多个进程之间共享

这样就失去了动态链接节省内存的一大优势!!!



那么 -fPIC 参数有什么作用呢?



解决 共享对象指令中绝对地址重定位问题基本思路:

把指令中那些需要修改的部分分离出来,和数据部分放在一起,这样指令部分可以保持不变,而数据部分可以个在每个进程中拥有一个副本



这种方案目前被称为:地址无关代码(PIC, Position-independent Code)



共享对象模块中的地址引用按照是否为跨模块分为

(1)模块内部引用

(2)模块外部引用

按照引用方式:

(1)指令引用

(2)数据访问



于是我们得到4中情况:

(1)模块内部 的 函数调用、跳转。

(2)模块内部 的 数据访问,比如模块中定义的全局变量、静态变量。

(3)模块外部 的 函数调用、跳转。

(4)模块外部 的 数据访问,比如其他模块中定义的全局变量。



p217

0
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics