📄 dyngen.c.svn-base
字号:
struct symtab_command *symtabcmd = 0;/* section */struct section *section_hdr;struct section *text_sec_hdr;uint8_t **sdata;/* relocs */struct relocation_info *relocs;/* symbols */EXE_SYM *symtab;struct nlist *symtab_std;char *strtab;/* indirect symbols */uint32_t *tocdylib;/* Utility functions */static inline char *find_str_by_index(int index){ return strtab+index;}/* Used by dyngen common code */static char *get_sym_name(EXE_SYM *sym){ char *name = find_str_by_index(sym->n_un.n_strx); if ( sym->n_type & N_STAB ) /* Debug symbols are ignored */ return "debug"; if(!name) return name; if(name[0]=='_') return name + 1; else return name;}/* find a section index given its segname, sectname */static int find_mach_sec_index(struct section *section_hdr, int shnum, const char *segname, const char *sectname){ int i; struct section *sec = section_hdr; for(i = 0; i < shnum; i++, sec++) { if (!sec->segname || !sec->sectname) continue; if (!strcmp(sec->sectname, sectname) && !strcmp(sec->segname, segname)) return i; } return -1;}/* find a section header given its segname, sectname */struct section *find_mach_sec_hdr(struct section *section_hdr, int shnum, const char *segname, const char *sectname){ int index = find_mach_sec_index(section_hdr, shnum, segname, sectname); if(index == -1) return NULL; return section_hdr+index;}static inline void fetch_next_pair_value(struct relocation_info * rel, unsigned int *value){ struct scattered_relocation_info * scarel; if(R_SCATTERED & rel->r_address) { scarel = (struct scattered_relocation_info*)rel; if(scarel->r_type != PPC_RELOC_PAIR) error("fetch_next_pair_value: looking for a pair which was not found (1)"); *value = scarel->r_value; } else { if(rel->r_type != PPC_RELOC_PAIR) error("fetch_next_pair_value: looking for a pair which was not found (2)"); *value = rel->r_address; }}/* find a sym name given its value, in a section number */static const char * find_sym_with_value_and_sec_number( int value, int sectnum, int * offset ){ int i, ret = -1; for( i = 0 ; i < nb_syms; i++ ) { if( !(symtab[i].n_type & N_STAB) && (symtab[i].n_type & N_SECT) && (symtab[i].n_sect == sectnum) && (symtab[i].st_value <= value) ) { if( (ret<0) || (symtab[i].st_value >= symtab[ret].st_value) ) ret = i; } } if( ret < 0 ) { *offset = 0; return 0; } else { *offset = value - symtab[ret].st_value; return get_sym_name(&symtab[ret]); }}/* * Find symbol name given a (virtual) address, and a section which is of type * S_NON_LAZY_SYMBOL_POINTERS or S_LAZY_SYMBOL_POINTERS or S_SYMBOL_STUBS */static const char * find_reloc_name_in_sec_ptr(int address, struct section * sec_hdr){ unsigned int tocindex, symindex, size; const char *name = 0; /* Sanity check */ if(!( address >= sec_hdr->addr && address < (sec_hdr->addr + sec_hdr->size) ) ) return (char*)0; if( sec_hdr->flags & S_SYMBOL_STUBS ){ size = sec_hdr->reserved2; if(size == 0) error("size = 0"); } else if( sec_hdr->flags & S_LAZY_SYMBOL_POINTERS || sec_hdr->flags & S_NON_LAZY_SYMBOL_POINTERS) size = sizeof(unsigned long); else return 0; /* Compute our index in toc */ tocindex = (address - sec_hdr->addr)/size; symindex = tocdylib[sec_hdr->reserved1 + tocindex]; name = get_sym_name(&symtab[symindex]); return name;}static const char * find_reloc_name_given_its_address(int address){ unsigned int i; for(i = 0; i < segment->nsects ; i++) { const char * name = find_reloc_name_in_sec_ptr(address, §ion_hdr[i]); if((long)name != -1) return name; } return 0;}static const char * get_reloc_name(EXE_RELOC * rel, int * sslide){ char * name = 0; struct scattered_relocation_info * sca_rel = (struct scattered_relocation_info*)rel; int sectnum = rel->r_symbolnum; int sectoffset; int other_half=0; /* init the slide value */ *sslide = 0; if(R_SCATTERED & rel->r_address) return (char *)find_reloc_name_given_its_address(sca_rel->r_value); if(rel->r_extern) { /* ignore debug sym */ if ( symtab[rel->r_symbolnum].n_type & N_STAB ) return 0; return get_sym_name(&symtab[rel->r_symbolnum]); } /* Intruction contains an offset to the symbols pointed to, in the rel->r_symbolnum section */ sectoffset = *(uint32_t *)(text + rel->r_address) & 0xffff; if(sectnum==0xffffff) return 0; /* Sanity Check */ if(sectnum > segment->nsects) error("sectnum > segment->nsects"); switch(rel->r_type) { case PPC_RELOC_LO16: fetch_next_pair_value(rel+1, &other_half); sectoffset |= (other_half << 16); break; case PPC_RELOC_HI16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (sectoffset << 16) | (uint16_t)(other_half & 0xffff); break; case PPC_RELOC_HA16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (sectoffset << 16) + (int16_t)(other_half & 0xffff); break; case PPC_RELOC_BR24: sectoffset = ( *(uint32_t *)(text + rel->r_address) & 0x03fffffc ); if (sectoffset & 0x02000000) sectoffset |= 0xfc000000; break; default: error("switch(rel->type) not found"); } if(rel->r_pcrel) sectoffset += rel->r_address; if (rel->r_type == PPC_RELOC_BR24) name = (char *)find_reloc_name_in_sec_ptr((int)sectoffset, §ion_hdr[sectnum-1]); /* search it in the full symbol list, if not found */ if(!name) name = (char *)find_sym_with_value_and_sec_number(sectoffset, sectnum, sslide); return name;}/* Used by dyngen common code */static const char * get_rel_sym_name(EXE_RELOC * rel){ int sslide; return get_reloc_name( rel, &sslide);}/* Used by dyngen common code */static host_ulong get_rel_offset(EXE_RELOC *rel){ struct scattered_relocation_info * sca_rel = (struct scattered_relocation_info*)rel; if(R_SCATTERED & rel->r_address) return sca_rel->r_address; else return rel->r_address;}/* load a mach-o object file */int load_object(const char *filename){ int fd; unsigned int offset_to_segment = 0; unsigned int offset_to_dysymtab = 0; unsigned int offset_to_symtab = 0; struct load_command lc; unsigned int i, j; EXE_SYM *sym; struct nlist *syment; fd = open(filename, O_RDONLY); if (fd < 0) error("can't open file '%s'", filename); /* Read Mach header. */ if (read(fd, &mach_hdr, sizeof (mach_hdr)) != sizeof (mach_hdr)) error("unable to read file header"); /* Check Mach identification. */ if (!check_mach_header(mach_hdr)) { error("bad Mach header"); } if (mach_hdr.cputype != CPU_TYPE_POWERPC) error("Unsupported CPU"); if (mach_hdr.filetype != MH_OBJECT) error("Unsupported Mach Object"); /* read segment headers */ for(i=0, j=sizeof(mach_hdr); i<mach_hdr.ncmds ; i++) { if(read(fd, &lc, sizeof(struct load_command)) != sizeof(struct load_command)) error("unable to read load_command"); if(lc.cmd == LC_SEGMENT) { offset_to_segment = j; lseek(fd, offset_to_segment, SEEK_SET); segment = malloc(sizeof(struct segment_command)); if(read(fd, segment, sizeof(struct segment_command)) != sizeof(struct segment_command)) error("unable to read LC_SEGMENT"); } if(lc.cmd == LC_DYSYMTAB) { offset_to_dysymtab = j; lseek(fd, offset_to_dysymtab, SEEK_SET); dysymtabcmd = malloc(sizeof(struct dysymtab_command)); if(read(fd, dysymtabcmd, sizeof(struct dysymtab_command)) != sizeof(struct dysymtab_command)) error("unable to read LC_DYSYMTAB"); } if(lc.cmd == LC_SYMTAB) { offset_to_symtab = j; lseek(fd, offset_to_symtab, SEEK_SET); symtabcmd = malloc(sizeof(struct symtab_command)); if(read(fd, symtabcmd, sizeof(struct symtab_command)) != sizeof(struct symtab_command)) error("unable to read LC_SYMTAB"); } j+=lc.cmdsize; lseek(fd, j, SEEK_SET); } if(!segment) error("unable to find LC_SEGMENT"); /* read section headers */ section_hdr = load_data(fd, offset_to_segment + sizeof(struct segment_command), segment->nsects * sizeof(struct section)); /* read all section data */ sdata = (uint8_t **)malloc(sizeof(void *) * segment->nsects); memset(sdata, 0, sizeof(void *) * segment->nsects); /* Load the data in section data */ for(i = 0; i < segment->nsects; i++) { sdata[i] = load_data(fd, section_hdr[i].offset, section_hdr[i].size); } /* text section */ text_sec_hdr = find_mach_sec_hdr(section_hdr, segment->nsects, SEG_TEXT, SECT_TEXT); i = find_mach_sec_index(section_hdr, segment->nsects, SEG_TEXT, SECT_TEXT); if (i == -1 || !text_sec_hdr) error("could not find __TEXT,__text section"); text = sdata[i]; /* Make sure dysym was loaded */ if(!(int)dysymtabcmd) error("could not find __DYSYMTAB segment"); /* read the table of content of the indirect sym */ tocdylib = load_data( fd, dysymtabcmd->indirectsymoff, dysymtabcmd->nindirectsyms * sizeof(uint32_t) ); /* Make sure symtab was loaded */ if(!(int)symtabcmd) error("could not find __SYMTAB segment"); nb_syms = symtabcmd->nsyms; symtab_std = load_data(fd, symtabcmd->symoff, symtabcmd->nsyms * sizeof(struct nlist)); strtab = load_data(fd, symtabcmd->stroff, symtabcmd->strsize); symtab = malloc(sizeof(EXE_SYM) * nb_syms); /* Now transform the symtab, to an extended version, with the sym size, and the C name */ for(i = 0, sym = symtab, syment = symtab_std; i < nb_syms; i++, sym++, syment++) { struct nlist *sym_follow, *sym_next = 0; unsigned int j; memset(sym, 0, sizeof(*sym)); if ( syment->n_type & N_STAB ) /* Debug symbols are skipped */ continue; memcpy(sym, syment, sizeof(*syment)); /* Find the following symbol in order to get the current symbol size */ for(j = 0, sym_follow = symtab_std; j < nb_syms; j++, sym_follow++) { if ( sym_follow->n_sect != 1 || sym_follow->n_type & N_STAB || !(sym_follow->n_value > sym->st_value)) continue; if(!sym_next) { sym_next = sym_follow; continue; } if(!(sym_next->n_value > sym_follow->n_value)) continue; sym_next = sym_follow; } if(sym_next) sym->st_size = sym_next->n_value - sym->st_value; else sym->st_size = text_sec_hdr->size - sym->st_value; } /* Find Reloc */ relocs = load_data(fd, text_sec_hdr->reloff, text_sec_hdr->nreloc * sizeof(struct relocation_info)); nb_relocs = text_sec_hdr->nreloc; close(fd); return 0;}#endif /* CONFIG_FORMAT_MACH */void get_reloc_expr(char *name, int name_size, const char *sym_name){ const char *p; if (strstart(sym_name, "__op_param", &p)) { snprintf(name, name_size, "param%s", p); } else if (strstart(sym_name, "__op_gen_label", &p)) { snprintf(name, name_size, "gen_labels[param%s]", p); } else {#ifdef HOST_SPARC if (sym_name[0] == '.') snprintf(name, name_size, "(long)(&__dot_%s)", sym_name + 1); else#endif snprintf(name, name_size, "(long)(&%s)", sym_name); }}#ifdef HOST_IA64#define PLT_ENTRY_SIZE 16 /* 1 bundle containing "brl" */struct plt_entry { struct plt_entry *next; const char *name; unsigned long addend;} *plt_list;static intget_plt_index (const char *name, unsigned long addend){ struct plt_entry *plt, *prev= NULL; int index = 0; /* see if we already have an entry for this target: */ for (plt = plt_list; plt; ++index, prev = plt, plt = plt->next) if (strcmp(plt->name, name) == 0 && plt->addend == addend) return index; /* nope; create a new PLT entry: */ plt = malloc(sizeof(*plt)); if (!plt) { perror("malloc");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -