FreeCalypso > hg > freecalypso-reveng
diff leo-obj/tool/reloc.c @ 130:87b82398a08b
leo-obj project subtree started, tiobjd tool moved into it
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Sun, 06 Apr 2014 22:14:39 +0000 |
parents | ticoff/reloc.c@d88f2f40e3ae |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/leo-obj/tool/reloc.c Sun Apr 06 22:14:39 2014 +0000 @@ -0,0 +1,164 @@ +/* + * 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); +}