pc端的linux下可以正常运行,放到arm11的开发板上运行就会报segment fault的错误

时间:2022-09-17 00:58:19
我写了个程序,放在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);


}

3 个解决方案

#1


你倒是把错误信息也贴出来啊

#2


我替换的是malloc函数和free函数的第一条指令,替换为跳转指令,跳向我自己的函数,当在开发板上运行时,执行到malloc或者free就报segment fault的错误。。不知道哪的原因,pc上的linux是可以正常运行的

#3


引用 2 楼  的回复:
我替换的是malloc函数和free函数的第一条指令,替换为跳转指令,跳向我自己的函数,当在开发板上运行时,执行到malloc或者free就报segment fault的错误。。不知道哪的原因,pc上的linux是可以正常运行的

都是分配内存的错误 

Linux中的内存管理

总结段错误(Segmentation fault)

#1


你倒是把错误信息也贴出来啊

#2


我替换的是malloc函数和free函数的第一条指令,替换为跳转指令,跳向我自己的函数,当在开发板上运行时,执行到malloc或者free就报segment fault的错误。。不知道哪的原因,pc上的linux是可以正常运行的

#3


引用 2 楼  的回复:
我替换的是malloc函数和free函数的第一条指令,替换为跳转指令,跳向我自己的函数,当在开发板上运行时,执行到malloc或者free就报segment fault的错误。。不知道哪的原因,pc上的linux是可以正常运行的

都是分配内存的错误 

Linux中的内存管理

总结段错误(Segmentation fault)