1 /*
2 * %CopyrightBegin%
3 *
4 * Copyright Ericsson AB 2006-2016. All Rights Reserved.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * %CopyrightEnd%
19 */
20 /*
21 ** This mini tool fixes an incompatibility between
22 ** Microsoft's tools, who dont like the virtual size being put in
23 ** the physical address field, but rely on the raw size field for
24 ** sizing the ".bss" section.
25 ** This fixes some of the problems with linking gcc compiled objects
26 ** together with MSVC dito.
27 **
28 ** Courtesy DJ Delorie for describing the COFF file format on
29 ** http://www.delorie.com/djgpp/doc/coff/
30 ** The coff structures are fetched from Microsofts headers though.
31 */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <stdarg.h>
37
38 #include <windows.h>
39 #include <winnt.h> /* Structure definitions for PE (COFF) */
40
41 static int dump_edit(char *filename, int edit);
42 static int v_printf(char *format, ...);
43
44
45 char *progname;
46 int verbouse = 0;
47
main(int argc,char ** argv)48 int main(int argc, char **argv)
49 {
50 int findex = 1;
51 int edit = 0;
52 int ret;
53
54 progname = argv[0];
55 if (argc == 1) {
56 fprintf(stderr,"Format : %s [-e] [-v] <filename>\n", progname);
57 return 1;
58 }
59 for (findex = 1;
60 findex < argc && (*argv[findex] == '-' || *argv[findex] == '/');
61 ++findex)
62 switch (argv[findex][1]) {
63 case 'e':
64 case 'E':
65 edit = 1;
66 break;
67 case 'v':
68 case 'V':
69 verbouse = 1;
70 default:
71 fprintf(stderr, "%s: unknown option %s\n", progname, argv[findex]);
72 break;
73 }
74 if (findex == argc) {
75 fprintf(stderr,"%s: No filenames given.\n", progname);
76 return 1;
77 }
78 for(; findex < argc; ++findex)
79 if ((ret = dump_edit(argv[findex],edit)) != 0)
80 return ret;
81 return 0;
82 }
83
dump_edit(char * filename,int edit)84 int dump_edit(char *filename, int edit)
85 {
86 FILE *f = fopen(filename, (edit) ? "r+b" : "rb");
87 IMAGE_FILE_HEADER filhdr;
88 IMAGE_SECTION_HEADER scnhdr;
89 int i;
90
91 if (f == NULL) {
92 fprintf(stderr, "%s: cannot open %s.\n", progname, filename);
93 return 1;
94 }
95
96 if (fread(&filhdr, sizeof(filhdr), 1, f) == 0) {
97 fprintf(stderr,"%s: Could not read COFF header from %s,"
98 " is this a PE (COFF) file?\n", progname, filename);
99 fclose(f);
100 return 1;
101 }
102 v_printf("File: %s\n", filename);
103 v_printf("Magic number: 0x%08x\n", filhdr.Machine);
104 v_printf("Number of sections: %d\n",filhdr.NumberOfSections);
105
106 if (fseek(f, (long) filhdr.SizeOfOptionalHeader, SEEK_CUR) != 0) {
107 fprintf(stderr,"%s: Could not read COFF optional header from %s,"
108 " is this a PE (COFF) file?\n", progname, filename);
109 fclose(f);
110 return 1;
111 }
112
113 for (i = 0; i < filhdr.NumberOfSections; ++i) {
114 if (fread(&scnhdr, sizeof(scnhdr), 1, f) == 0) {
115 fprintf(stderr,"%s: Could not read section header from %s,"
116 " is this a PE (COFF) file?\n", progname, filename);
117 fclose(f);
118 return 1;
119 }
120 v_printf("Section %s:\n", scnhdr.Name);
121 v_printf("Physical address: 0x%08x\n", scnhdr.Misc.PhysicalAddress);
122 v_printf("Size: 0x%08x\n", scnhdr.SizeOfRawData);
123 if (scnhdr.Misc.PhysicalAddress != 0 &&
124 scnhdr.SizeOfRawData == 0) {
125 printf("Section header %s in file %s will confuse MSC linker, "
126 "virtual size is 0x%08x and raw size is 0\n",
127 scnhdr.Name, filename, scnhdr.Misc.PhysicalAddress,
128 scnhdr.SizeOfRawData);
129 if (edit) {
130 scnhdr.SizeOfRawData = scnhdr.Misc.PhysicalAddress;
131 scnhdr.Misc.PhysicalAddress = 0;
132 if (fseek(f, (long) -((long)sizeof(scnhdr)), SEEK_CUR) != 0 ||
133 fwrite(&scnhdr, sizeof(scnhdr), 1, f) == 0) {
134 fprintf(stderr,"%s: could not edit file %s.\n",
135 progname, filename);
136 fclose(f);
137 return 1;
138 }
139 printf("Edited object, virtual size is now 0, and "
140 "raw size is 0x%08x.\n", scnhdr.SizeOfRawData);
141 } else {
142 printf("Specify option '-e' to correct the problem.\n");
143 }
144 }
145 }
146 fclose(f);
147 return 0;
148 }
149
150
v_printf(char * format,...)151 static int v_printf(char *format, ...)
152 {
153 va_list ap;
154 int ret = 0;
155 if (verbouse) {
156 va_start(ap, format);
157 ret = vfprintf(stdout, format, ap);
158 va_end(ap);
159 }
160 return ret;
161 }
162
163