FreeCalypso > hg > freecalypso-reveng
view leo-obj/tool/reloc.c @ 133:daeaa5950d10
tiobjd: Thumb bl w/o reloc: find symbol if there is one
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Mon, 07 Apr 2014 01:22:09 +0000 |
parents | 87b82398a08b |
children |
line wrap: on
line source
/* * Handling of relocation records */ #include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include "filestruct.h" #include "intstruct.h" #include "coffconst.h" #include "globals.h" extern unsigned get_u16(), get_u32(); cmd_rawrel() { unsigned n, m; struct internal_scnhdr *sec; struct external_reloc *rel; get_int_section_table(); for (n = 0; n < nsections; n++) { sec = sections + n; if (!sec->nreloc) continue; printf("%s:\n\n", sec->name); rel = (struct external_reloc *)(filemap + sec->reloc_offset); printf("Location SymIndex Rsvd Type\n"); for (m = 0; m < sec->nreloc; m++, rel++) printf("%08X %08X %04X %04X\n", get_u32(rel->r_vaddr), get_u32(rel->r_symndx), get_u16(rel->r_reserved), get_u16(rel->r_type)); putchar('\n'); } exit(0); } void get_relocs_of_sec(sec) struct internal_scnhdr *sec; { unsigned n; struct external_reloc *extrel; struct internal_reloc *intrel; unsigned lastloc, symidx; if (sec->int_relocs) return; if (!sec->nreloc) { fprintf(stderr, "BUG: get_relocs_of_sec() called for section \"%s\" w/o relocs\n", sec->name); exit(1); } intrel = malloc(sizeof(struct internal_reloc) * sec->nreloc); if (!intrel) { perror("malloc"); exit(1); } sec->int_relocs = intrel; extrel = (struct external_reloc *)(filemap + sec->reloc_offset); for (n = 0; n < sec->nreloc; n++, extrel++, intrel++) { intrel->location = get_u32(extrel->r_vaddr); if (n && intrel->location <= lastloc) { fprintf(stderr, "error: non-increasing reloc order in section \"%s\"\n", sec->name); exit(1); } lastloc = intrel->location; symidx = get_u32(extrel->r_symndx); if (symidx == 0xFFFFFFFF) intrel->sym = 0; else if (symidx >= nsymtab || !symtab[symidx]) { fprintf(stderr, "error: reloc references invalid symbol #%u in section \"%s\"\n", symidx, sec->name); exit(1); } else intrel->sym = symtab[symidx]; intrel->type = get_u16(extrel->r_type); switch (intrel->type) { case RTYPE_LONG: intrel->typestr = "Word32"; break; case RTYPE_THUMB_BL: intrel->typestr = "Thumb_BL"; break; case RTYPE_ARM_B: intrel->typestr = "ARM_B"; break; default: fprintf(stderr, "error: reloc in section \"%s\" of unexpected type 0x%x\n", sec->name, intrel->type); exit(1); } if (get_u16(extrel->r_reserved)) fprintf(stderr, "warning: reloc in section \"%s\" has non-zero reserved field\n", sec->name); } } cmd_reloc() { unsigned n, m; struct internal_scnhdr *sec; struct internal_reloc *rel; char *symname; get_int_section_table(); get_int_symbol_table(); for (n = 0; n < nsections; n++) { sec = sections + n; if (!sec->nreloc) continue; printf("%s:\n\n", sec->name); get_relocs_of_sec(sec); rel = sec->int_relocs; printf("Location Type Symbol relative to\n"); for (m = 0; m < sec->nreloc; m++, rel++) { if (rel->sym) symname = rel->sym->name; else symname = "<none>"; printf("%08X %-8s %s\n", rel->location, rel->typestr, symname); } putchar('\n'); } exit(0); } struct internal_reloc * find_reloc(sec, loc) struct internal_scnhdr *sec; unsigned loc; { struct internal_reloc *rel; unsigned m; rel = sec->int_relocs; for (m = 0; m < sec->nreloc; m++, rel++) { if (rel->location == loc) return(rel); if (rel->location > loc) return(0); } return(0); } struct internal_reloc * find_word32_reloc(sec, loc) struct internal_scnhdr *sec; unsigned loc; { struct internal_reloc *rel; rel = find_reloc(sec, loc); if (rel && rel->type != RTYPE_LONG) rel = 0; return(rel); }