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