comparison tool/coff.c @ 6:87e9f30f5f86

ti-libpatch: patching implemented
author Space Falcon <falcon@ivan.Harhan.ORG>
date Sat, 06 Jun 2015 04:51:15 +0000
parents
children
comparison
equal deleted inserted replaced
5:5ba13fd0e737 6:87e9f30f5f86
1 /*
2 * This C module implements COFF operations for ti-libpatch.
3 */
4
5 #include <sys/types.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <strings.h>
10 #include "coffstruct.h"
11 #include "patchinfo.h"
12 #include "globals.h"
13
14 struct external_scnhdr *sections_raw;
15 unsigned nsections;
16 unsigned strtab_offset;
17
18 static unsigned
19 get_u16(ptr)
20 u_char *ptr;
21 {
22 return ptr[0] | ptr[1] << 8;
23 }
24
25 static unsigned
26 get_u32(ptr)
27 u_char *ptr;
28 {
29 return ptr[0] | ptr[1] << 8 | ptr[2] << 16 | ptr[3] << 24;
30 }
31
32 parse_coff_hdr()
33 {
34 struct external_filehdr *filehdr_struct;
35 unsigned symtab_offset;
36 unsigned nsymtab;
37
38 filehdr_struct = (struct external_filehdr *) member_body;
39 if (get_u16(filehdr_struct->f_magic) != 0xC2) {
40 fprintf(stderr,
41 "error: member \"%s\" is not a TI COFF2 object\n",
42 member_name);
43 exit(1);
44 }
45 if (get_u16(filehdr_struct->f_target_id) != 0x97) {
46 fprintf(stderr, "error: member \"%s\" is not a TMS470 object\n",
47 member_name);
48 exit(1);
49 }
50 if (get_u16(filehdr_struct->f_opthdr)) {
51 fprintf(stderr,
52 "error: member \"%s\" has the \"optional\" header present\n",
53 member_name);
54 exit(1);
55 }
56 sections_raw = (struct external_scnhdr *)
57 (member_body + sizeof(struct external_filehdr));
58 nsections = get_u16(filehdr_struct->f_nscns);
59 symtab_offset = get_u32(filehdr_struct->f_symptr);
60 nsymtab = get_u32(filehdr_struct->f_nsyms);
61 strtab_offset = symtab_offset +
62 sizeof(struct external_syment) * nsymtab;
63 return(0);
64 }
65
66 static struct external_scnhdr *
67 find_section_shortname(soughtname)
68 char *soughtname;
69 {
70 unsigned i;
71 struct external_scnhdr *scnhdr;
72
73 for (i = 0; i < nsections; i++) {
74 scnhdr = sections_raw + i;
75 if (!strncmp(scnhdr->s_name, soughtname, 8))
76 return(scnhdr);
77 }
78 return(0);
79 }
80
81 static struct external_scnhdr *
82 find_section_longname(soughtname)
83 char *soughtname;
84 {
85 unsigned i;
86 struct external_scnhdr *scnhdr;
87 u_char *np, *longname;
88
89 for (i = 0; i < nsections; i++) {
90 scnhdr = sections_raw + i;
91 np = scnhdr->s_name;
92 if (np[0] || np[1] || np[2] || np[3])
93 continue;
94 longname = member_body + strtab_offset + get_u32(np + 4);
95 if (!strcmp(longname, soughtname))
96 return(scnhdr);
97 }
98 return(0);
99 }
100
101 static struct external_scnhdr *
102 find_section(soughtname)
103 char *soughtname;
104 {
105 if (strlen(soughtname) <= 8)
106 return find_section_shortname(soughtname);
107 else
108 return find_section_longname(soughtname);
109 }
110
111 apply_patch(patch)
112 struct patch_desc *patch;
113 {
114 struct external_scnhdr *scnhdr;
115 unsigned data_offset, section_size;
116
117 scnhdr = find_section(patch->section);
118 if (!scnhdr) {
119 fprintf(stderr,
120 "error: could not find section \"%s\" in member \"%s\"\n",
121 patch->section, member_name);
122 exit(1);
123 }
124 data_offset = get_u32(scnhdr->s_scnptr);
125 section_size = get_u32(scnhdr->s_size);
126 if (data_offset + section_size > member_size) {
127 fprintf(stderr,
128 "error: section \"%s\" in member \"%s\" exceeds member size\n",
129 patch->section, member_name);
130 exit(1);
131 }
132 if (patch->offset >= section_size) {
133 fprintf(stderr,
134 "error: patch offset 0x%x in section \"%s\" exceeds section size\n",
135 patch->offset, patch->section);
136 exit(1);
137 }
138 /* do it! */
139 member_body[data_offset + patch->offset] = patch->new_byte;
140 return(0);
141 }