获取本程序绝对路径

经常看到有人提问在linux中如何获取当前应用程序的绝对路径,   却很少有人能比较好的解答.   现转贴www.linuxforum.net上的一篇文章中的一段,   希望能对受这个问题困扰的人有帮助.  
   
   
  13.12   如何获取当前进程对应之静态映像文件的绝对路径  
   
  A:   hushui110@水木清华  
   
  这是一个x86/Linux   Kernel   2.4.7-10系统中利用proc获取绝对路径的例子  
   
  --------------------------------------------------------------------------  
   
  /*  
   
  *   gcc   -Wall   -pipe   -g   -static   -o   myprog_2   myprog_2.c  
   
  */  
   
  #include   <stdio.h>  
   
  #include   <stdlib.h>  
   
  #include   <unistd.h>  
   
   
   
  #define   MAXBUFSIZE   1024  
   
   
   
  int   main   (   int   argc,   char   *   argv[]   )  
   
  {  
   
          char   buf[   MAXBUFSIZE   ];  
   
          int     count;  
   
   
   
          count   =   readlink(   "/proc/self/exe",   buf,   MAXBUFSIZE   );  
   
          if   (   count   <   0   ||   count   >=   MAXBUFSIZE   )  
   
          {  
   
                  printf(   "Failed/n"   );  
   
                  return(   EXIT_FAILURE   );  
   
          }  
   
          buf[   count   ]   =   '/0';  
   
          printf(   "/proc/self/exe   ->   [%s]/n",   buf   );  
   
          return(   EXIT_SUCCESS   );  
   
  }     /*   end   of   main   */  
   
   
  --------------------------------------------------------------------------  
   
  [scz@   /home/scz/src]>   echo   $PATH  
  /bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:.  
  [scz@   /home/scz/src]>   ./myprog_2  
  /proc/self/exe   ->   [/home/scz/src/myprog_2]  
  [scz@   /home/scz/src]>   ../src/myprog_2  
  /proc/self/exe   ->   [/home/scz/src/myprog_2]  
  [scz@   /home/scz/src]>   myprog_2  
  /proc/self/exe   ->   [/home/scz/src/myprog_2]  
  [scz@   /home/scz/src]>  
   
  显然这里直接给出了最期待的结果,没有冗余信息。  
   
  A:   scz   <scz@nsfocus.com>   &   microcat   <lgx@nsfocus.com>  
  2000-03-18  
   
  下面在x86/Linux   Kernel   2.4.7-10上演示、讨论  
   
  --------------------------------------------------------------------------  
   
  *  
   
  *   gcc   -Wall   -pipe   -g   -static   -o   myprog   myprog.c  
   
  */  
   
  #include   <stdio.h>  
   
  #include   <stdlib.h>  
   
   
   
  int   main   (   int   argc,   char   *   argv[]   )  
   
  {  
   
          return(   EXIT_SUCCESS   );  
   
  }     /*   end   of   main   */  
   
   
  --------------------------------------------------------------------------  
   
  [scz@   /home/scz/src]>   gcc   -Wall   -pipe   -g   -static   -o   myprog   myprog.c  
  [scz@   /home/scz/src]>   echo   $PATH  
  /bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:.  
  [scz@   /home/scz/src]>   gdb   ./myprog  
  (gdb)   b   main  
  (gdb)   r  
  (gdb)   x/17s   0xbfffff00  
  0xbfffff00:   "SHLVL=1"  
  0xbfffff08:   "_=/bin/bash"  
  0xbfffff14:   "SHELL=/bin/bash"  
  0xbfffff24:   "HOSTTYPE=i386"  
  0xbfffff32:   "OSTYPE=linux-gnu"  
  0xbfffff43:   "HISTSIZE=1000"  
  0xbfffff51:   "TERM=vt100"  
  0xbfffff5c:   "HOME=/home/scz"  
  0xbfffff6b:   "SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass"  
  0xbfffff9e:   "PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:."  
  0xbfffffd2:   "LESSCHARSET=latin1"  
  0xbfffffe5:   "/home/scz/src/./myprog"   <--   注意这个输出  
  0xbffffffc:   ""  
  0xbffffffd:   ""  
  0xbffffffe:   ""  
  0xbfffffff:   ""  
  0xc0000000:   <Address   0xc0000000   out   of   bounds>  
  [scz@   /home/scz/src]>   gdb   myprog  
  (gdb)   b   main  
  (gdb)   r  
  (gdb)   x/17s   0xbfffff00  
  0xbfffff00:   "z"  
  0xbfffff02:   "SHLVL=1"  
  0xbfffff0a:   "_=/bin/bash"  
  0xbfffff16:   "SHELL=/bin/bash"  
  0xbfffff26:   "HOSTTYPE=i386"  
  0xbfffff34:   "OSTYPE=linux-gnu"  
  0xbfffff45:   "HISTSIZE=1000"  
  0xbfffff53:   "TERM=vt100"  
  0xbfffff5e:   "HOME=/home/scz"  
  0xbfffff6d:   "SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass"  
  0xbfffffa0:   "PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:."  
  0xbfffffd4:   "LESSCHARSET=latin1"  
  0xbfffffe7:   "/home/scz/src/myprog"   <--   注意这个输出  
  0xbffffffc:   ""  
  0xbffffffd:   ""  
  0xbffffffe:   ""  
  0xbfffffff:   ""  
  [scz@   /home/scz/src]>   gdb   ../src/myprog  
  (gdb)   b   main  
  (gdb)   r  
  (gdb)   x/17s   0xbfffff00  
  0xbfffff00:   "=1"  
  0xbfffff03:   "_=/bin/bash"  
  0xbfffff0f:   "SHELL=/bin/bash"  
  0xbfffff1f:   "HOSTTYPE=i386"  
  0xbfffff2d:   "OSTYPE=linux-gnu"  
  0xbfffff3e:   "HISTSIZE=1000"  
  0xbfffff4c:   "TERM=vt100"  
  0xbfffff57:   "HOME=/home/scz"  
  0xbfffff66:   "SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass"  
  0xbfffff99:   "PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:."  
  0xbfffffcd:   "LESSCHARSET=latin1"  
  0xbfffffe0:   "/home/scz/src/../src/myprog"   <--   注意这个输出  
  0xbffffffc:   ""  
  0xbffffffd:   ""  
  0xbffffffe:   ""  
  0xbfffffff:   ""  
  0xc0000000:   <Address   0xc0000000   out   of   bounds>  
  [scz@   /home/scz/src]>  
   
  这是ELF文件在Linux系统中加载进内存之后的布局简图  
   
  --------------------------------------------------------------------------  
  0x08048000   code   .text,代码,只读  
  data   .data,包含已经初始化的数据,只读  
  bss   .bss,未初始化数据,初始化成0,读/写  
  ...   堆区,动态分配获取的内存从.bss往内存高端增长  
  ...   (heap),读/写  
  ...  
  stack   栈区,起始地址大于0xBFFF0000  
  arguments   main()的形参  
  environment   环境变量区域  
  program   name   execve()第一形参,不是argv[0]  
  0xBFFFFFFC   null(dword)   最后四个字节固定为零  
  0xC0000000  
  --------------------------------------------------------------------------  
   
  通常动态链接库被映射到0x40000000往高端的地址。对于Linux,如果打了不可执行  
  堆栈内核补丁,动态链接库被映射到0x40000000往低端的地址。tt说就是以前的映射  
  地址减去0x40000000。打了补丁后使得通过字符串拷贝(strcpy)传递shellcode相对  
  复杂化,需要更多技巧。  
   
  program   name处不一定是绝对路径,实际对应了execve()第一形参。一般从shell上  
  启动进程,shell根据PATH环境变量自动搜索匹配出一个路径,未必是绝对路径。假  
  设PATH环境变量中有当前目录(.),所执行的程序也只在当前目录下有,直接指定程  
  序名(myprog)执行时,shell会向execve()第一形参传递"./myprog"。注意,execve  
  第一形参未必是绝对路径。用gdb加载后再执行,情况有所不同。如果gdb命令行上指  
  定的程序名非绝对路径,gdb在调用execve()之前会调用getcwd()拼接在程序名之前,  
   
  此时不依赖PATH环境变量。所以用gdb调试溢出程序时应该在命令行上指定绝对路径,  
   
  避免不必要的偏移调整。  
   
  现在来看这样一个演示程序  
   
  --------------------------------------------------------------------------  
   
  /*  
   
  *   gcc   -Wall   -pipe   -g   -static   -o   myprog_1   myprog_1.c  
   
  */  
   
  #include   <stdio.h>  
   
  #include   <stdlib.h>  
   
   
   
  extern   char   **environ;  
   
   
   
  int   main   (   int   argc,   char   *   argv[]   )  
   
  {  
   
          char   *path   =   (   char   *   )(   0xc0000000   -   5   );  
   
   
   
          while   (   *--path   );  
   
          ++path;  
   
          printf(   "path               -->   %08x   [%s]/n",   (   unsigned   int   )path,   path   );  
   
          printf(   "argv               -->   %08x/n",   (   unsigned   int   )argv   );    
   
          printf(   "argv[0]         -->   %08x   [%s]/n",   (   unsigned   int   )argv[0],  
  argv[0]   );  
   
          printf(   "environ         -->   %08x/n",   (   unsigned   int   )environ   );    
   
          printf(   "environ[0]   -->   %08x   [%s]/n",   (   unsigned   int   )environ[0],  
  environ[0]   );  
   
          return(   EXIT_SUCCESS   );  
   
  }     /*   end   of   main   */  
   
   
  --------------------------------------------------------------------------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值