map 文件

内容

显示你的存储实际使用情况,哪些变量、函数,位于哪个地址和section。

 

 生成

通过gcc参数-Wl,-Map,:

gcc -o helloworld helloworld.c -Wl,-Map,file_name.map

 

通过ld参数-Map:

ld -Map file_name.map helloworld.o -o helloworld

 

 

例子

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>


int g_var1;
char *g_var2 = "hello world !";

int test_func(int arg) {

    static char *s_var1 = NULL;
    static int s_var2 = 255;

    int var = arg * 10;

    return var;
}

static void *pthread_proc(void *arg)
{
     /* 线程pthread开始运行 */
     printf("pthread start!\n");

     /* 令主线程继续执行 */
     sleep(2);

     return NULL;
}

int main(int argc, char **argv) {

    pthread_t tidp;

    g_var1 = 100;

    printf("%s\n", g_var2);

    printf("main=%016llx, func=%016llx, var=%016llx\n", (long long)main, (long long)test_func, (long long)g_var2);

    test_func(g_var1);

    pthread_create(&tidp, NULL, pthread_proc, NULL);
    pthread_join(tidp, NULL);

    printf("exit !\n");

    return 0;
}

程序基本包含代码的所有关键点:全局变量、静态变量、局部变量、函数、链接库。执行编译命令生成map文件和可执行文件。

gcc -o helloworld helloworld.c -Wl,-Map,helloworld.map -lpthread

 

程序执行结果:

$  ./helloworld                                                    
hello world !
main=000055c70b2dd86e, func=000055c70b2dd82a, var=000055c70b2dd9c8
pthread start!
exit !

 

map文件片段1:

按需库被包含以满足文件 (符号) 引用

libpthread.so.0               /tmp/ccnK3bV5.o (pthread_create@@GLIBC_2.2.5)
libc.so.6                     /tmp/ccnK3bV5.o (puts@@GLIBC_2.2.5)

分配公共符号
公共符号            大小              文件

g_var1              0x4               /tmp/ccnK3bV5.o

 

可以看到链接库(libpthread)的引用符号(pthread_create函数)、全局变量(g_var1)。
注意:静态变量和静态函数不会出现在map文件中!

map文件片段2:

 .text          0x0000000000000700       0x2b /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o
                0x0000000000000700                _start
 .text          0x000000000000072b        0x0 /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crti.o
 *fill*         0x000000000000072b        0x5 
 .text          0x0000000000000730       0xda /usr/lib/gcc/x86_64-linux-gnu/7/crtbeginS.o
 .text          0x000000000000080a       0xfc /tmp/ccnK3bV5.o
                0x000000000000080a                test_func
                0x000000000000084e                main

 

可以看到函数test_func和main的信息,其地址与程序运行时打印出的地址有必然联系(最后一个字节相同)。理论上打印的地址和map中的地址(物理地址)应该是一样的,但由于Linux系统的虚拟地址机制,打印出来的是虚拟地址,但是地址排列是一致的,所以最后一个字节相同。

map文件片段3:

.bss            0x0000000000201028       0x18
 *(.dynbss)
 .dynbss        0x0000000000201028        0x0 /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o
 *(.bss .bss.* .gnu.linkonce.b.*)
 .bss           0x0000000000201028        0x0 /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o
 .bss           0x0000000000201028        0x0 /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crti.o
 .bss           0x0000000000201028        0x1 /usr/lib/gcc/x86_64-linux-gnu/7/crtbeginS.o
 *fill*         0x0000000000201029        0x7 
 .bss           0x0000000000201030        0x8 /tmp/ccnK3bV5.o
 .bss           0x0000000000201038        0x0 /usr/lib/x86_64-linux-gnu/libc_nonshared.a(elf-init.oS)
 .bss           0x0000000000201038        0x0 /usr/lib/gcc/x86_64-linux-gnu/7/crtendS.o
 .bss           0x0000000000201038        0x0 /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crtn.o
 *(COMMON)
 COMMON         0x0000000000201038        0x4 /tmp/ccnK3bV5.o
                0x0000000000201038                g_var1

由于g_var1是未初始化的全局变量,应该被分配在bss段,从map文件也可以验证这一点。

map文件片段4:

.data          0x0000000000201010       0x14 /tmp/ccnK3bV5.o
                0x0000000000201010                g_var2

.rodata        0x00000000000009c8       0x50 /tmp/ccPjpRD1.o

 

同理,g_var2是初始化的全局变量,分配在数据段(.data)。g_var2的初始化数据“hello world !”放在只读数据段(.rodata)。

 

上一篇:《自己动手写CPU》 安装Openrisc_ubuntu虚拟机 安装GNU工具链


下一篇:Liunx目录