利用GCC 的-pg 屬性調試linux app/driver

來源:互聯網
上載者:User

[原創文章] 作者:whq_ddd@163.com          歡迎轉載,轉載請指明出處: http://blog.csdn.net/whqwhqwhq/article/details/6853084

GCC的-pg 會為每個function call 插入一個_mcount的routine 功能,這個_mcount的原型為

          void _mcount(void);

在linux調試時常不知道driver死在了哪個function中, 如果寫自己的 _mcount 並且在其中列印出caller那不就解決了!

需要解決的兩個問題是

 1. 寫自己的 void _mcount(void), 並且注意此function 編譯時間不能加 -pg屬性,否則就會自己無限調用自己,直到stack溢出死機!

 2. 在_count 中尋找caller的地址。這是個小痛點。

經測試是可行的。我在mips平台上做的實驗,以下內容的mips32平台相關。

mips利用ra寄存器儲存caller的返回地址,並且儲存在sp中。相當反組譯碼代碼為

00400840 <_mcount>:
  400840:   27bdffe0    addiu   sp,sp,-32
  400844:   afbf001c    sw  ra,28(sp)
  400848:   afbe0018    sw  s8,24(sp)
  40084c:   03a0f021    move    s8,sp

即ra會儲存在sp+28處,發現sp+28處即為ra地址!只要將sp+28值取出即可,這地址為function執行完後下一次指令。 

這裡取了個巧!因為sp是動態,在實際代碼編譯出來之前,你不知道_mcount會用多少sp。先隨便寫一個值,如下

void _mcount(void)
{
  int addr_calling;
  asm(
      "lw %0,12($30)\n" 
      "addi %0,%0,-8\n"
      "nop\n"
      :"=r"(addr_calling));
  printf("Calling function address: 0x%p\n", addr_calling);
}

然後利用objdump查此處代碼:

00400840 <_mcount>:
  400840:   27bdffe0    addiu   sp,sp,-32
  400844:   afbf001c    sw  ra,28(sp)
  400848:   afbe0018    sw  s8,24(sp)
  40084c:   03a0f021    move    s8,sp
  400850:   23c2000c    lw    v0,12(s8)
  400854:   2042fffc    addi    v0,v0,-8

  400858:   00000000    nop

發現sp利用了32個位元組!將c code更改一下,為

void _mcount(void)
{
  int addr_calling;
  asm(
      "lw %0,28($30)\n" 
      "addi %0,%0,-8\n"
      "nop\n"
      :"=r"(addr_calling));
  printf("Calling function address: 0x%p\n", addr_calling);
}


在application 中證明是可行的,在調試驅動程式時也應該是可行的,畢竟這是gcc  的特性。

貼整個source code:

file: mcount.c

#include <stdio.h>
void _mcount(void)
{
  int addr_calling;
  asm(
        "lw %0,28($30)\n" 
      "addi %0,%0,-8\n"
      "nop\n"
      :"=r"(addr_calling));
  printf("Calling function address: 0x%p\n", addr_calling);
}


file: main.c

#include "stdio.h"
extern void _mcount(void);
void call_sub1(int );

int main()
{
  int a=10;
  printf("in main function.\n");
  call_sub1(a);
  return 0;
}

void call_sub1(int a)
{
  printf("in call_sub1, a is %d \n", a);
}

file: Makefile

CC = /opt/timesys/dbau1300/toolchain/bin/mipsisa32el-timesys-linux-gnu-gcc
OBJDUMP = /opt/timesys/dbau1300/toolchain/bin/mipsisa32el-timesys-linux-gnu-objdump

all:
    $(CC) -c main.c -pg
    $(CC) -c mcount.c
    $(CC) main.o mcount.o -o test1 -pg
    $(OBJDUMP) -D test1 >dis-pg.S
~
~

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.