FreeCalypso > hg > freecalypso-reveng
view objgrep/mkpattern.c @ 215:d69f7512e3c1
Pirelli: documented and verified the checksum scheme used for the factory block
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 25 Dec 2016 23:48:16 +0000 |
parents | 77cd647375e5 |
children |
line wrap: on
line source
/* * 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; nreloc_int++; } else if (sym->class == C_EXT && sym->scnum == 0) { irel->extsym = sym; irel->secbase = 0; nreloc_ext++; } else if (sym->class == C_STAT && sym->section && !strcmp(sym->name, sym->section->name)) { irel->secbase = sym->section; irel->extsym = 0; nreloc_int++; } 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); }