FreeCalypso > hg > tcs211-patches
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 } |