2017-10-27 3 views
0

저는 nm 기본을 구현하는 프로젝트에서 메모리 매핑 mmap을 사용하고 있습니다. 위의 fat_header 구조체 인 마하 - 오와 지방 바이너리 사이 link 유일한 차이점에 따르면유니버설/팻 바이너리 파일 구문 분석

void  handle_64(char *ptr) 
{ 
    int      ncmds; 
    struct mach_header_64 *header; 
    struct load_command  *lc; 
    struct symtab_command *sym; 
    int      i; 

    i = 0; 
    header = (struct mach_header_64 *)ptr; 
    ncmds = header->ncmds; 
    lc = (void *)ptr + sizeof(*header); 
    while (i < ncmds) 
    { 
     if (lc->cmd == LC_SYMTAB) 
     { 
      sym = (struct symtab_command *)lc; 
      build_list (sym->nsyms, sym->symoff, sym->stroff, ptr); 
      break; 
     } 
     lc = (void *) lc + lc->cmdsize; 
     i++; 
    } 
} 

, 단순히

으로 스킵 : 나는 코드를 사용하여 64 비트 바이너리를 구문 분석 할 수 있었다
lc = (void *)ptr + sizeof(struct fat_header) + sizeof(struct mach_header_64); 

나를로드 _ 명령 영역 (segfault)으로 가져 오지 못합니다. fat/universal 바이너리의 load 명령에 어떻게 액세스합니까?

저는 macOS High Sierra를 실행하는 64 비트 Mac에서 작업하고 있습니다. 고맙습니다.

답변

1

가지고있어 여러 문제 :

  • 당신이 전화 "지방 헤더 '에 링크 된 그 블로그 그냥 struct fat_header 이상 무엇입니까.
  • 는 아무데도 그것은 마하-O 헤더 그래서 지방 후 즉시 퍼팅, 그것은 (일반적으로 마하-O 세그먼트는 전체 페이지에 정렬 할 단지 후, 지방 헤더 다음에 즉시에 따라 것이라는 점을 보장 할 수 없습니다 헤더가 작동하지 않을 수도 있음).
  • 64 비트 슬라이스가 이진 파일에서 첫 번째가 아니며 아무 것도 없을 것입니다. 이 모든 것을 고려

, 당신 유용한 결과를 얻기의 희망을 원하는 경우 (단지 그것을 무시하지) 지방 헤더를 구문 분석 할 필요. 다음과 같이

이제 fat_header가 정의 : 첫째, 나는 보통 지방 바이너리 볼 마법 값이 다르게 나타 코멘트에도 불구하고, FAT_CIGAM보다는 FAT_MAGIC

struct fat_header { 
    uint32_t magic;  /* FAT_MAGIC or FAT_MAGIC_64 */ 
    uint32_t nfat_arch; /* number of structs that follow */ 
}; 

입니다

(하지만 알아서 -이 있다는 것을 의미 뚱뚱한 머리말에있는 정수는 작은 엔디안보다는 오히려 큰 엔디안이다!). 그러나 둘째, 특정 구조체 즉,이 헤더를 따르는 것이 표시됩니다 :

struct fat_arch { 
    cpu_type_t cputype; /* cpu specifier (int) */ 
    cpu_subtype_t cpusubtype; /* machine specifier (int) */ 
    uint32_t offset;  /* file offset to this object file */ 
    uint32_t size;  /* size of this object file */ 
    uint32_t align;  /* alignment as a power of 2 */ 
}; 

이는로드 명령과 함께 "씬"마하-O 헤더가하는 같은 방식으로 작동합니다. fat_arch.offset은 파일의 맨 처음부터의 오프셋입니다. 그 다음, 그것은 지방 마하-O의 모든 조각을 인쇄하는 것은 매우 간단합니다 : 그것은 buf의 길이를 알고하지 않기 때문에 위의 기능이 불완전 것을

#include <stdio.h> 
#include <mach-o/fat.h> 

#define SWAP32(x) ((((x) & 0xff000000) >> 24) | (((x) & 0xff0000) >> 8) | (((x) & 0xff00) << 8) | (((x) & 0xff) << 24)) 

void print_fat_header(void *buf) 
{ 
    struct fat_header *hdr = buf; 
    if(hdr->magic != FAT_CIGAM) 
    { 
     fprintf(stderr, "bad magic: %08x\n", hdr->magic); 
     return; 
    } 
    struct fat_arch *archs = (struct fat_arch*)(hdr + 1); 
    uint32_t num = SWAP32(hdr->nfat_arch); 
    for(size_t i = 0; i < num; ++i) 
    { 
     const char *name = "unknown"; 
     switch(SWAP32(archs[i].cputype)) 
     { 
      case CPU_TYPE_I386:  name = "i386";  break; 
      case CPU_TYPE_X86_64: name = "x86_64"; break; 
      case CPU_TYPE_ARM:  name = "arm";  break; 
      case CPU_TYPE_ARM64: name = "arm64";  break; 
     } 
     uint32_t off = SWAP32(archs[i].offset); 
     uint32_t magic = *(uint32_t*)((uintptr_t)buf + off); 
     printf("%08x-%08x: %-8s (magic %8x)\n", off, off + SWAP32(archs[i].size), name, magic); 
    } 
} 

참고 때문에 할 수 없습니다 및 액세스 확인하지 않습니다 그것에 대한 기억. 심각한 구현에서는, 주어진 버퍼 밖에서 절대로 읽지 않도록해야합니다. 코드가 segfault 된 사실은 충분한 데이터 sanitisation을하지 않는다는 것을 암시합니다.