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);
+}