FreeCalypso > hg > freecalypso-reveng
diff objgrep/mkpattern.c @ 167:c25367bb7656
objgrep: written, compiles
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Fri, 04 Jul 2014 00:54:33 +0000 |
parents | |
children | ed1a06bf525d |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/objgrep/mkpattern.c Fri Jul 04 00:54:33 2014 +0000 @@ -0,0 +1,178 @@ +/* + * objgrep: preparation of matching pattern + */ + +#include <sys/types.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include "filestruct.h" +#include "intstruct.h" +#include "coffconst.h" +#include "globals.h" + +extern unsigned get_u16(), get_u32(); + +static unsigned +arm_branch_reloc(origbits, location) + u_char *origbits; + unsigned location; +{ + unsigned word, dest; + + word = get_u32(origbits + location); + if ((word & 0x0E000000) != 0x0A000000) { + fprintf(stderr, + "error: invalid ARM_B reloc: opcode not B or BL\n"); + exit(2); + } + dest = (word & 0x00FFFFFF) << 2; + if (dest & 0x02000000) + dest |= 0xFC000000; + dest += location + 8; + return(dest); +} + +static unsigned +thumb_bl_reloc(origbits, location) + u_char *origbits; + unsigned location; +{ + unsigned ins1, ins2; + unsigned dest; + + ins1 = get_u16(origbits + location); + ins2 = get_u16(origbits + location + 2); + if ((ins1 & 0xF800) != 0xF000 || (ins2 & 0xF800) != 0xF800) { + fprintf(stderr, + "error: invalid Thumb_BL reloc: opcode not BL\n"); + exit(2); + } + dest = ((ins1 & 0x7FF) << 12) | ((ins2 & 0x7FF) << 1); + if (dest & 0x00400000) + dest |= 0xFF800000; + dest += location + 4; + return(dest); +} + +prepare_pattern() +{ + u_char *origbits; + unsigned pad, n; + struct internal_reloc *irel; + struct external_reloc *xrel; + unsigned lastloc, symidx; + struct internal_syment *sym; + + origbits = objfilemap + grep_section->data_offset; + pattern_len = (grep_section->size + 3) & ~3; + pattern_match = malloc(pattern_len); + if (!pattern_match) { + perror("malloc"); + exit(2); + } + bcopy(origbits, pattern_match, grep_section->size); + pattern_mask = malloc(pattern_len); + if (!pattern_mask) { + perror("malloc"); + exit(2); + } + memset(pattern_mask, 0xFF, grep_section->size); + pad = pattern_len - grep_section->size; + if (pad) { + bzero(pattern_match + grep_section->size, pad); + bzero(pattern_mask + grep_section->size, pad); + } + if (!grep_section->nreloc) + return(0); + xrel = (struct external_reloc *) + (objfilemap + grep_section->reloc_offset); + irel = malloc(sizeof(struct internal_reloc) * grep_section->nreloc); + if (!irel) { + perror("malloc"); + exit(2); + } + relocs = irel; + for (n = 0; n < grep_section->nreloc; n++, xrel++, irel++) { + irel->location = get_u32(xrel->r_vaddr); + if (n && irel->location < lastloc) { + fprintf(stderr, "error: non-increasing reloc order\n"); + exit(2); + } + lastloc = irel->location + 4; + if (lastloc > grep_section->size) { + fprintf(stderr, + "error: reloc spills past the end of the section\n"); + exit(2); + } + symidx = get_u32(xrel->r_symndx); + if (symidx == 0xFFFFFFFF) + sym = 0; + else if (symidx >= nsymtab || !symtab[symidx]) { + fprintf(stderr, + "error: reloc references invalid symbol #%u\n", + symidx); + exit(2); + } else + sym = symtab[symidx]; + if (sym && sym->value) { + fprintf(stderr, + "error: symbol #%u referenced by reloc has nonzero value\n"); + exit(2); + } + if (!sym) { + irel->secbase = grep_section; + irel->extsym = 0; + } else if (sym->class == C_EXT && !sym->scnum == 0) { + irel->extsym = sym; + irel->secbase = 0; + } else if (sym->class == C_STAT && sym->section && + !strcmp(sym->name, sym->section->name)) { + irel->secbase = sym->section; + irel->extsym = 0; + } else { + fprintf(stderr, "error: unable to grok reloc\n"); + exit(2); + } + irel->type = get_u16(xrel->r_type); + switch (irel->type) { + case RTYPE_LONG: + if (irel->location & 3) { +align_error: fprintf(stderr, "error: misaligned reloc\n"); + exit(2); + } + irel->addend = get_u32(origbits + irel->location); + *(uint32_t *)(pattern_match + irel->location) = 0; + *(uint32_t *)(pattern_mask + irel->location) = 0; + break; + case RTYPE_ARM_B: + if (irel->location & 3) + goto align_error; + irel->addend = arm_branch_reloc(origbits, + irel->location); + bzero(pattern_match + irel->location, 3); + bzero(pattern_mask + irel->location, 3); + break; + case RTYPE_THUMB_BL: + if (irel->location & 1) + goto align_error; + irel->addend = thumb_bl_reloc(origbits, irel->location); + pattern_match[irel->location+0] = 0; + pattern_match[irel->location+1] &= 0xF8; + pattern_match[irel->location+2] = 0; + pattern_match[irel->location+3] &= 0xF8; + pattern_mask[irel->location+0] = 0; + pattern_mask[irel->location+1] = 0xF8; + pattern_mask[irel->location+2] = 0; + pattern_mask[irel->location+3] = 0xF8; + break; + default: + fprintf(stderr, "error: reloc type 0x%x unsupported\n", + irel->type); + exit(2); + } + } + return(1); +}