comparison 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
comparison
equal deleted inserted replaced
166:861f5ca49581 167:c25367bb7656
1 /*
2 * objgrep: preparation of matching pattern
3 */
4
5 #include <sys/types.h>
6 #include <stdio.h>
7 #include <stdint.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <strings.h>
11 #include "filestruct.h"
12 #include "intstruct.h"
13 #include "coffconst.h"
14 #include "globals.h"
15
16 extern unsigned get_u16(), get_u32();
17
18 static unsigned
19 arm_branch_reloc(origbits, location)
20 u_char *origbits;
21 unsigned location;
22 {
23 unsigned word, dest;
24
25 word = get_u32(origbits + location);
26 if ((word & 0x0E000000) != 0x0A000000) {
27 fprintf(stderr,
28 "error: invalid ARM_B reloc: opcode not B or BL\n");
29 exit(2);
30 }
31 dest = (word & 0x00FFFFFF) << 2;
32 if (dest & 0x02000000)
33 dest |= 0xFC000000;
34 dest += location + 8;
35 return(dest);
36 }
37
38 static unsigned
39 thumb_bl_reloc(origbits, location)
40 u_char *origbits;
41 unsigned location;
42 {
43 unsigned ins1, ins2;
44 unsigned dest;
45
46 ins1 = get_u16(origbits + location);
47 ins2 = get_u16(origbits + location + 2);
48 if ((ins1 & 0xF800) != 0xF000 || (ins2 & 0xF800) != 0xF800) {
49 fprintf(stderr,
50 "error: invalid Thumb_BL reloc: opcode not BL\n");
51 exit(2);
52 }
53 dest = ((ins1 & 0x7FF) << 12) | ((ins2 & 0x7FF) << 1);
54 if (dest & 0x00400000)
55 dest |= 0xFF800000;
56 dest += location + 4;
57 return(dest);
58 }
59
60 prepare_pattern()
61 {
62 u_char *origbits;
63 unsigned pad, n;
64 struct internal_reloc *irel;
65 struct external_reloc *xrel;
66 unsigned lastloc, symidx;
67 struct internal_syment *sym;
68
69 origbits = objfilemap + grep_section->data_offset;
70 pattern_len = (grep_section->size + 3) & ~3;
71 pattern_match = malloc(pattern_len);
72 if (!pattern_match) {
73 perror("malloc");
74 exit(2);
75 }
76 bcopy(origbits, pattern_match, grep_section->size);
77 pattern_mask = malloc(pattern_len);
78 if (!pattern_mask) {
79 perror("malloc");
80 exit(2);
81 }
82 memset(pattern_mask, 0xFF, grep_section->size);
83 pad = pattern_len - grep_section->size;
84 if (pad) {
85 bzero(pattern_match + grep_section->size, pad);
86 bzero(pattern_mask + grep_section->size, pad);
87 }
88 if (!grep_section->nreloc)
89 return(0);
90 xrel = (struct external_reloc *)
91 (objfilemap + grep_section->reloc_offset);
92 irel = malloc(sizeof(struct internal_reloc) * grep_section->nreloc);
93 if (!irel) {
94 perror("malloc");
95 exit(2);
96 }
97 relocs = irel;
98 for (n = 0; n < grep_section->nreloc; n++, xrel++, irel++) {
99 irel->location = get_u32(xrel->r_vaddr);
100 if (n && irel->location < lastloc) {
101 fprintf(stderr, "error: non-increasing reloc order\n");
102 exit(2);
103 }
104 lastloc = irel->location + 4;
105 if (lastloc > grep_section->size) {
106 fprintf(stderr,
107 "error: reloc spills past the end of the section\n");
108 exit(2);
109 }
110 symidx = get_u32(xrel->r_symndx);
111 if (symidx == 0xFFFFFFFF)
112 sym = 0;
113 else if (symidx >= nsymtab || !symtab[symidx]) {
114 fprintf(stderr,
115 "error: reloc references invalid symbol #%u\n",
116 symidx);
117 exit(2);
118 } else
119 sym = symtab[symidx];
120 if (sym && sym->value) {
121 fprintf(stderr,
122 "error: symbol #%u referenced by reloc has nonzero value\n");
123 exit(2);
124 }
125 if (!sym) {
126 irel->secbase = grep_section;
127 irel->extsym = 0;
128 } else if (sym->class == C_EXT && !sym->scnum == 0) {
129 irel->extsym = sym;
130 irel->secbase = 0;
131 } else if (sym->class == C_STAT && sym->section &&
132 !strcmp(sym->name, sym->section->name)) {
133 irel->secbase = sym->section;
134 irel->extsym = 0;
135 } else {
136 fprintf(stderr, "error: unable to grok reloc\n");
137 exit(2);
138 }
139 irel->type = get_u16(xrel->r_type);
140 switch (irel->type) {
141 case RTYPE_LONG:
142 if (irel->location & 3) {
143 align_error: fprintf(stderr, "error: misaligned reloc\n");
144 exit(2);
145 }
146 irel->addend = get_u32(origbits + irel->location);
147 *(uint32_t *)(pattern_match + irel->location) = 0;
148 *(uint32_t *)(pattern_mask + irel->location) = 0;
149 break;
150 case RTYPE_ARM_B:
151 if (irel->location & 3)
152 goto align_error;
153 irel->addend = arm_branch_reloc(origbits,
154 irel->location);
155 bzero(pattern_match + irel->location, 3);
156 bzero(pattern_mask + irel->location, 3);
157 break;
158 case RTYPE_THUMB_BL:
159 if (irel->location & 1)
160 goto align_error;
161 irel->addend = thumb_bl_reloc(origbits, irel->location);
162 pattern_match[irel->location+0] = 0;
163 pattern_match[irel->location+1] &= 0xF8;
164 pattern_match[irel->location+2] = 0;
165 pattern_match[irel->location+3] &= 0xF8;
166 pattern_mask[irel->location+0] = 0;
167 pattern_mask[irel->location+1] = 0xF8;
168 pattern_mask[irel->location+2] = 0;
169 pattern_mask[irel->location+3] = 0xF8;
170 break;
171 default:
172 fprintf(stderr, "error: reloc type 0x%x unsupported\n",
173 irel->type);
174 exit(2);
175 }
176 }
177 return(1);
178 }