微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > ARM技术讨论 > pc端的linux下可以正常运行,放到arm11的开发板上运行就会...

pc端的linux下可以正常运行,放到arm11的开发板上运行就会...

时间:10-02 整理:3721RD 点击:
我写了个程序,放在pc上的linux编译之后可以正常运行,但是交叉编译完之后放到开发板上运行就会报segment fault的错误(错误是在执行被修改的函数中报出来的),板子(linux)没有什么问题,交叉编译器也没问题,我写的程序的功能是当调用一个函数时,就会立马跳转到另一个函数执行,该功能是通过修改函数的入口的第一条指令来完成,修改为跳转指令,跳转的值是相对的地址距离的差(相对跳转)。哪位大侠可以帮我调试一下啊,跪谢!已经折磨了我好几个星期了。这个程序的跳转是碰到malloc或free就跳转到我自己的函数中,来收集一些信息。代码如下,复制直接就可以运行。函数的入口指令的修改通过ContainerAdd()这个函数来实现的。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/mman.h>

#define FUNCLISTLENTH 100
#define BYTE char
#define MAX_FUNC_NUM 10
#define VOS_VOID  void
#define BOOL int
#define size_t unsigned int

int FALSE = 0;
int TRUE = 1;

typedef int (*FUNCPTR)();

int content[][5] = {{0}};
FUNCPTR newFuncList[FUNCLISTLENTH]={NULL};
FUNCPTR oldFuncList[FUNCLISTLENTH]={NULL};

unsigned long oldFuncJumpOffset[FUNCLISTLENTH]={0};
unsigned long newFuncJumpOffset[FUNCLISTLENTH]={0};

BYTE oldFuncFirstCode[MAX_FUNC_NUM] = {0};

extern tmpRepFuncList[FUNCLISTLENTH] = {0};


/*
   函数名称: ChangeProtection
   功能   : 修改某段内存的保护模式
   参数   :
          [in]  ulFrom   待写内存开始地址
  [in]  ulLength 待写内存长度
  [in]  ulMode   模式
   返回值  :成功返回TRUE 失败返回FALSE
*/
unsigned int ChangeProtection(unsigned int ulFrom,unsigned int ulLength,unsigned int ulMode)
{
printf("\nI am   ChangeProtection !\n");
int iRtn;
unsigned int ulLastPageEnd;
unsigned int ulFirstPageStart;


ulFirstPageStart = ulFrom - (ulFrom % 4096);

ulLastPageEnd = ulFrom + ulLength;

ulLastPageEnd += 4096 - (ulLastPageEnd % 4096);


iRtn = mprotect((VOS_VOID *)ulFirstPageStart,ulLastPageEnd-ulFirstPageStart,ulMode);
if( 0 != iRtn)
{
printf("Call mprotect fail in ChangeProtection !\n");
return FALSE;
}
printf("\nI am   ChangeProtection Runover!\n");
return TRUE;

}


/*
   函数名称: ModProtectMemContent
   功能   : 完成修改某段保护内存的内容
   参数   :
          [in]  pBassAddress   待写内存开始地址
  [in]  ucCmd          待写内存长度
  [in]  dwData         数据区内容
   返回值  :成功返回TRUE 失败返回FALSE
*/


unsigned int ModProtectMemContent(void* pBaseAddress, BYTE ucCmd, unsigned long  dwData)  
{

printf("\nI am   ModProtectionMemContent !\n");
        BYTE aBuf[10] = {0};
BOOL bRtn;

if((ChangeProtection((unsigned int)pBaseAddress, 5, PROT_EXEC | PROT_READ | PROT_WRITE)) == FALSE)
{

return FALSE;

}

//准备要填入的指令机器码,需要修改五个字节内容
aBuf[0] = ucCmd;//0XE9为相对跳转指令的机器码
aBuf[1] = (BYTE)(dwData & 0xFF);
aBuf[2] = (BYTE)((dwData & 0xFF00)>> 8);
aBuf[3] = (BYTE)((dwData & 0xFF0000)>> 16);
aBuf[4] = (BYTE)((dwData & 0xFF000000)>> 24);

//修改老函数入口处的指令
bRtn = memcpy(pBaseAddress, aBuf, 5);
if(!bRtn)
{
printf("Modify old func entry instruct fail in ModProtectMemContent!'\n'");
return FALSE;

}


if((ChangeProtection((unsigned int)pBaseAddress ,5 ,PROT_EXEC | PROT_READ)) == FALSE)
{
return FALSE;

}
printf("\nI am   ModProtectionMemContent Runover!\n");
return TRUE;
}



/*
   函数名称: RecoverReplaceOldFunc
   功能   :在新函数调用完原函数后恢复对原函数的修改
   参数   :
          [in]  oldFunc    旧函数指针
   返回值  :成功返回TRUE 失败返回FALSE
*/

unsigned int RecoverReplaceOldFunc(FUNCPTR oldFunc)
{

printf("\nI am   RecoverReplaceOldFunc !\n");
BOOL bRtn;
int i;
//printf("**********Enter RecoverReplaceOldFunc!**********\n");
for(i=0;i<MAX_FUNC_NUM;i++)
{

if(oldFuncList[i] == oldFunc)
{
  if((ChangeProtection(oldFunc, 5, PROT_EXEC | PROT_READ | PROT_WRITE)) == 0)
    {
      return 0;
    }
  bRtn = memcpy(oldFunc, content[i], 5);
  oldFuncList[i] = NULL;
newFuncList[i] = NULL;
oldFuncJumpOffset[i] = 0;
newFuncJumpOffset[i] = 0;
oldFuncFirstCode[i] = 0;
  if(!bRtn)
    {
      printf("memcpy fail in RecoverReplaceOldFunc!\n");
      return FALSE;
    }
  //printf("**********Exit RecoverReplaceOldFunc!**********\n");
  printf("\nI am   RecoverReplaceOldFunc Runover!\n");
  return TRUE;
}

}

printf("Can not find the old func!\n");
return FALSE;
}

int ContainerAdd(void *pOldFunc,void *pNewFunc)
{


printf("\nI am   ContainerAdd !\n");
BOOL bRtn;

//printf("**********Enter ContainerAdd!**********\n");

unsigned long dwNewInstructOffset = 0;
unsigned long dwOldJumpOffset = 0;
unsigned long dwTmpJumpOffset = 0;
unsigned long dwNewOffset = 0;

int i;
for(i = 0; i < MAX_FUNC_NUM; i++)
{
if(newFuncList[i] == NULL)
{

        //得到临时替代函数相对原函数的偏移
  memcpy(content[i],pOldFunc,5);
  tmpRepFuncList[i]=(unsigned long)pNewFunc;
  dwTmpJumpOffset = (unsigned long)pNewFunc - (unsigned long )pOldFunc - 5;
  dwNewInstructOffset = (unsigned long)pOldFunc - (unsigned long)pNewFunc - 5;

  bRtn = ModProtectMemContent(pOldFunc, 0XE9, dwTmpJumpOffset);
  if(!bRtn)
  {
    printf("ModProtectMemContent fail in ContainerAdd !\n");
    return FALSE;
  }
   
  newFuncList[i]=(FUNCPTR)pNewFunc;
  oldFuncList[i]=(FUNCPTR)pOldFunc;
  newFuncJumpOffset[i] = dwNewInstructOffset;
  oldFuncJumpOffset[i]= dwOldJumpOffset;
  oldFuncFirstCode[i] = *(BYTE*)pOldFunc;
printf("\nI am   ContainerAdd RunOver!\n");
  return 1;
}

}


if(i>=MAX_FUNC_NUM)
{
printf("The func list is full !\n");
return TRUE;
}


return TRUE;
}


/********************************************************************************/
//函数执行跳转指令后 所跳向的函数
void * my_malloc(size_t len)
{


printf("\nMy_malloc run\n");
FILE *q=fopen("MemoryMallocInfo.txt","a+");
fprintf(q,"\r\n");
  char* temp;
  RecoverReplaceOldFunc(malloc);
  temp=(char *)malloc(len);
  ContainerAdd(malloc,my_malloc);
  printf("\nMalloc Address : %10p Length : %d\n",temp,len);
  fprintf(q,"  %s       %10p   
   %d
  %d\n",__FILE__,temp,__LINE__,len);
  fclose(q);

  printf("\nMy_malloc run RunOver !\n");
  return temp;

}


//函数执行跳转指令后 所跳向的函数

void *my_free(void *p)
{

printf("\nMy_free Run !\n");
FILE *q=fopen("MemoryFreeInfo.txt","a+");
fprintf(q,"\r\n");
char* temp;
int len;
len=sizeof(*p);
//printf("\nName :%s  :  Line\n",*file,line);
RecoverReplaceOldFunc(free);
printf("\nFree Address : %10p        Length : %d\n",p,len);
  fprintf(q,"  %s       %10p\n",__FILE__,p);
free(p);
  p=NULL;
  fclose(q);
  ContainerAdd(free,my_free);
  printf("\nMy_free Run RunOver!\n");
   
}


  
//跳转函数的启动
int test()
{


printf("\nTest run\n");
FILE *p=fopen("MemoryMallocInfo.txt","a+");
fprintf(p,"\r\n");
fprintf(p,"
FileName  
Address  
LineNumber  
TotalByte\n");
fprintf(p,"\r\n");
FILE *q=fopen("MemoryFreeInfo.txt","a+");
fprintf(q,"\r\n");
fprintf(q,"
FileName  
Address\n");
fprintf(q,"\r\n");
fclose(p);
fclose(q);

  ContainerAdd(malloc,my_malloc);

  ContainerAdd(free,my_free);
  printf("The Address of malloc() = %p.\nThe Address of my_malloc = %p.\n", malloc, my_malloc);
printf("\nTest run Runover\n");
  return 0;
}

void main()
{
test();
  char *zhang=malloc(sizeof(char)*100);
  char *p1=malloc(20*sizeof(char));//337行
  char *p2=malloc(24*sizeof(char));//338行
  char *p3=malloc(28*sizeof(char));//339行
  char *p4=malloc(32*sizeof(char));//340行
  char *p5=malloc(36*sizeof(char));//341行
free(zhang);

free(p1);
free(p2);
free(p3);
free(p4);
free(p5);

}

我复制运行了,你这个还是有很多错误啊。可能是你copy的格式不对吧。

哥,arm11下的相对跳转指令的机器码也是0xE9吗?
X86数值是小端模式保存,arm是不是也是小端模式?
要不加修改跨平台移植,不要使用没弄明白的机器码

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top