VirtualBox

source: vbox/trunk/src/bldprogs/genalias.cpp@ 96040

Last change on this file since 96040 was 96040, checked in by vboxsync, 2 years ago

bldprogs/genalias: Added a weak alias generator program (for COFF, OMF). Based on r3951. bugref:10261

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.2 KB
Line 
1/* $Id: genalias.cpp 96040 2022-08-04 22:00:57Z vboxsync $ */
2/** @file
3 * genalias - generate a number of alias objects.
4 *
5 * @note The code has its origin with kLIBC and was added to VBox by the author.
6 */
7
8/*
9 * Copyright (C) 2022 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 */
19
20
21/*********************************************************************************************************************************
22* Header Files *
23*********************************************************************************************************************************/
24#include <stdarg.h>
25#include <stdio.h>
26#include <iprt/stdint.h>
27#include <string.h>
28#include <time.h>
29#include <assert.h>
30
31#define GENALIAS_UNDERSCORED 0
32
33
34
35static int Error(const char *pszFormat, ...)
36{
37 va_list va;
38 fprintf(stderr, "genalias: error: ");
39 va_start(va, pszFormat);
40 vfprintf(stderr, pszFormat, va);
41 va_end(va);
42 return 1;
43}
44
45static int SyntaxError(const char *pszFormat, ...)
46{
47 va_list va;
48 fprintf(stderr, "genalias: syntax error: ");
49 va_start(va, pszFormat);
50 vfprintf(stderr, pszFormat, va);
51 va_end(va);
52 return 1;
53}
54
55static int WriteAliasObjectAOUT(FILE *pOutput, const char *pszAlias, const char *pszReal)
56{
57#pragma pack(1)
58 /* ASSUMES 32-bit target. */
59 struct AoutHdr
60 {
61 uint32_t a_info;
62 uint32_t a_text;
63 uint32_t a_data;
64 uint32_t a_bss;
65 uint32_t a_syms;
66 uint32_t a_entry;
67 uint32_t a_trsize;
68 uint32_t a_drsize;
69 } Hdr;
70#define OMAGIC 0407
71 struct AoutSym
72 {
73 uint32_t n_strx;
74 uint8_t n_type;
75 int8_t n_other;
76 uint16_t n_desc;
77 uint32_t n_value;
78 } Sym;
79#define N_EXT 1
80#define N_INDR 10
81#pragma pack()
82 const uint32_t cchAlias = (uint32_t)strlen(pszAlias);
83 const uint32_t cchReal = (uint32_t)strlen(pszReal);
84 uint32_t u32;
85
86 /* write the header. */
87 memset(&Hdr, 0, sizeof(Hdr));
88 Hdr.a_info = OMAGIC;
89 Hdr.a_syms = 2 * sizeof(Sym);
90 if (fwrite(&Hdr, sizeof(Hdr), 1, pOutput) != 1)
91 return -2;
92
93 /* The alias symbol. */
94 Sym.n_strx = 4 + cchReal + 1 + GENALIAS_UNDERSCORED;
95 Sym.n_type = N_INDR | N_EXT;
96 Sym.n_other = 0;
97 Sym.n_desc = 0;
98 Sym.n_value = 0;
99 if (fwrite(&Sym, sizeof(Sym), 1, pOutput) != 1)
100 return -2;
101
102 /* The real symbol. */
103 Sym.n_strx = 4;
104 Sym.n_type = N_EXT;
105 Sym.n_other = 0;
106 Sym.n_desc = 0;
107 Sym.n_value = 0;
108 if (fwrite(&Sym, sizeof(Sym), 1, pOutput) != 1)
109 return -2;
110
111 /* the string table. */
112 u32 = 4 + cchReal + 1 + cchAlias + 1 + GENALIAS_UNDERSCORED * 2;
113 if (fwrite(&u32, 4, 1, pOutput) != 1)
114 return -2;
115#if GENALIAS_UNDERSCORED
116 if (fputc('_', pOutput) == EOF)
117 return -2;
118#endif
119 if (fwrite(pszReal, cchReal + 1, 1, pOutput) != 1)
120 return -2;
121#if GENALIAS_UNDERSCORED
122 if (fputc('_', pOutput) == EOF)
123 return -2;
124#endif
125 if (fwrite(pszAlias, cchAlias + 1, 1, pOutput) != 1)
126 return -2;
127 return 0;
128}
129
130static int WriteAliasObjectCOFF(FILE *pOutput, const char *pszAlias, const char *pszReal)
131{
132#pragma pack(1)
133 struct CoffHdr
134 {
135 uint16_t Machine;
136 uint16_t NumberOfSections;
137 uint32_t TimeDateStamp;
138 uint32_t PointerToSymbolTable;
139 uint32_t NumberOfSymbols;
140 uint16_t SizeOfOptionalHeader;
141 uint16_t Characteristics;
142 } Hdr;
143 struct CoffShdr
144 {
145 char Name[8];
146 uint32_t VirtualSize;
147 uint32_t VirtualAddress;
148 uint32_t SizeOfRawData;
149 uint32_t PointerToRawData;
150 uint32_t PointerToRelocations;
151 uint32_t PointerToLinenumbers;
152 uint16_t NumberOfRelocations;
153 uint16_t NumberOfLinenumbers;
154 uint32_t Characteristics;
155 } Shdr;
156#define IMAGE_SCN_LNK_INFO 0x200
157#define IMAGE_SCN_LNK_REMOVE 0x800
158 struct CoffSym
159 {
160 union
161 {
162 char ShortName[8];
163 struct
164 {
165 uint32_t Zeros;
166 uint32_t Offset;
167 } s;
168 } u;
169 uint32_t Value;
170 uint16_t SectionNumber;
171 uint16_t Type;
172 uint8_t StorageClass;
173 uint8_t NumberOfAuxSymbols;
174 } Sym;
175#define IMAGE_SYM_UNDEFINED 0
176#define IMAGE_SYM_TYPE_NULL 0
177#define IMAGE_SYM_CLASS_EXTERNAL 2
178#define IMAGE_SYM_CLASS_WEAK_EXTERNAL 105
179 struct CoffAuxWeakExt
180 {
181 uint32_t TagIndex;
182 uint32_t Characteristics;
183 uint8_t padding[10];
184 } Aux;
185#define IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3
186 assert(sizeof(Hdr) == 20); assert(sizeof(Sym) == 18); assert(sizeof(Aux) == sizeof(Sym));
187#pragma pack()
188 const uint32_t cchAlias = (uint32_t)strlen(pszAlias);
189 const uint32_t cchReal = (uint32_t)strlen(pszReal);
190 uint32_t u32;
191
192 /* write the header. */
193 Hdr.Machine = 0 /*unknown*/; //0x14c /* i386 */;
194 Hdr.NumberOfSections = 1;
195 Hdr.TimeDateStamp = time(NULL);
196 Hdr.PointerToSymbolTable = sizeof(Hdr) + sizeof(Shdr);
197 Hdr.NumberOfSymbols = 3;
198 Hdr.SizeOfOptionalHeader = 0;
199 Hdr.Characteristics = 0;
200 if (fwrite(&Hdr, sizeof(Hdr), 1, pOutput) != 1)
201 return -2;
202
203 /* The directive section. */
204 if (Hdr.NumberOfSections == 1)
205 {
206 memset(&Shdr, 0, sizeof(Shdr));
207 memcpy(Shdr.Name, ".drectve", 8);
208 Shdr.Characteristics = IMAGE_SCN_LNK_REMOVE | IMAGE_SCN_LNK_INFO;
209 if (fwrite(&Shdr, sizeof(Shdr), 1, pOutput) != 1)
210 return -2;
211 }
212
213 /* The real symbol. */
214 memset(&Sym, 0, sizeof(Sym));
215 Sym.u.s.Offset = 4;
216 Sym.SectionNumber = IMAGE_SYM_UNDEFINED;
217 Sym.Type = IMAGE_SYM_TYPE_NULL;
218 Sym.StorageClass = IMAGE_SYM_CLASS_EXTERNAL;
219 if (fwrite(&Sym, sizeof(Sym), 1, pOutput) != 1)
220 return -2;
221
222 /* The alias symbol. */
223 memset(&Sym, 0, sizeof(Sym));
224 Sym.u.s.Offset = GENALIAS_UNDERSCORED + cchReal + 1 + 4;
225 Sym.SectionNumber = IMAGE_SYM_UNDEFINED;
226 Sym.Type = IMAGE_SYM_TYPE_NULL;
227 Sym.StorageClass = IMAGE_SYM_CLASS_WEAK_EXTERNAL;
228 Sym.NumberOfAuxSymbols = 1;
229 if (fwrite(&Sym, sizeof(Sym), 1, pOutput) != 1)
230 return -2;
231
232 /* aux entry for that. */
233 memset(&Aux, 0, sizeof(Aux));
234 Aux.TagIndex = 0;
235 Aux.Characteristics = IMAGE_WEAK_EXTERN_SEARCH_ALIAS;
236 if (fwrite(&Aux, sizeof(Aux), 1, pOutput) != 1)
237 return -2;
238
239 /* the string table. */
240 u32 = 4 + cchReal + 1 + cchAlias + 1 + GENALIAS_UNDERSCORED * 2;
241 if (fwrite(&u32, 4, 1, pOutput) != 1)
242 return -2;
243#if GENALIAS_UNDERSCORED
244 if (fputc('_', pOutput) == EOF)
245 return -2;
246#endif
247 if (fwrite(pszReal, cchReal + 1, 1, pOutput) != 1)
248 return -2;
249#if GENALIAS_UNDERSCORED
250 if (fputc('_', pOutput) == EOF)
251 return -2;
252#endif
253 if (fwrite(pszAlias, cchAlias + 1, 1, pOutput) != 1)
254 return -2;
255 return 0;
256}
257
258static int WriteAliasObjectELF(FILE *pOutput, const char *pszAlias, const char *pszReal)
259{
260 RT_NOREF(pOutput, pszAlias, pszReal);
261 fprintf(stderr, "ELF does not support proper aliasing, only option seems to be adding weak symbols with the strong one.\n");
262 return -1;
263}
264
265static int WriteAliasObjectOMF(FILE *pOutput, const char *pszAlias, const char *pszReal)
266{
267 const uint32_t cchAlias = (uint32_t)strlen(pszAlias);
268 const uint32_t cchReal = (uint32_t)strlen(pszReal);
269 const uint32_t cchName = cchAlias > 250 ? 250 : cchAlias;
270 uint32_t cch;
271
272 if (cchReal >= 250)
273 return Error("Symbol '%s' is too long!\n", pszReal);
274 if (cchAlias >= 250)
275 return Error("Symbol '%s' is too long!\n", pszAlias);
276
277 /* THEADR */
278 fputc(0x80, pOutput);
279 cch = cchAlias + 2;
280 fputc(cch & 0xff, pOutput);
281 fputc(cch >> 8, pOutput);
282 fputc(cchAlias, pOutput);
283 fwrite(pszAlias, cchAlias, 1, pOutput);
284 fputc(0, pOutput); /* CRC */
285
286 /* ALIAS */
287 fputc(0xc6, pOutput);
288 cch = cchAlias + 1 + cchReal + 1 + GENALIAS_UNDERSCORED * 2 + 1;
289 fputc(cch & 0xff, pOutput);
290 fputc(cch >> 8, pOutput);
291 fputc(cchAlias + GENALIAS_UNDERSCORED, pOutput);
292 if (GENALIAS_UNDERSCORED)
293 fputc('_', pOutput);
294 fwrite(pszAlias, cchAlias, 1, pOutput);
295 fputc(cchReal + GENALIAS_UNDERSCORED, pOutput);
296 if (GENALIAS_UNDERSCORED)
297 fputc('_', pOutput);
298 fwrite(pszReal, cchReal, 1, pOutput);
299 fputc(0, pOutput); /* CRC */
300
301 /* MODEND32 */
302 fputc(0x8b, pOutput);
303 fputc(2, pOutput);
304 fputc(0, pOutput);
305 fputc(0, pOutput);
306 if (fputc(0, pOutput) == EOF) /* CRC */
307 return -2;
308 return 0;
309}
310
311static int WriteAliasObjectMACHO(FILE *pOutput, const char *pszAlias, const char *pszReal)
312{
313 RT_NOREF(pOutput, pszAlias, pszReal);
314 fprintf(stderr, "Mach-O support not implemented yet\n");
315 return -1;
316}
317
318static int CreateAlias(char *pszBuf, size_t cchInput, char *pszFileBuf, char *pszFilename,
319 int (*pfnWriter)(FILE *, const char *, const char *))
320{
321 char *pszAlias = pszBuf;
322 char *pszReal;
323 char *pszFile;
324 FILE *pOutput;
325 int rc;
326 RT_NOREF(cchInput);
327
328 /*
329 * Parse input.
330 */
331 pszReal = strchr(pszBuf, '=');
332 if (!pszReal)
333 return Error("Malformed request: '%s'\n", pszBuf);
334 *pszReal++ = '\0';
335
336 pszFile = strchr(pszReal, '=');
337 if (pszFile)
338 {
339 *pszFile++ = '\0';
340 strcpy(pszFilename, pszFile);
341 }
342 else
343 strcat(strcpy(pszFilename, pszAlias), ".o");
344
345 /*
346 * Open the output file.
347 */
348 pOutput = fopen(pszFileBuf, "wb");
349 if (!pOutput)
350 return Error("Failed to open '%s' for writing!\n", pszFileBuf);
351 rc = pfnWriter(pOutput, pszAlias, pszReal);
352 if (rc == -2)
353 rc = Error("Write error writing '%s'!\n", pszFileBuf);
354 fclose(pOutput);
355 return rc;
356}
357
358
359static int Syntax(void)
360{
361 printf("syntax: genalias -f <format> -D <output-dir> alias=real[=file] [alias2=real2[=file2] [..]]\n"
362 " OR\n"
363 " genalias -f <format> -D <output-dir> -r <response-file>\n"
364 "\n"
365 "Format can be: aout, coff or omf\n"
366 "The responsefile is a single argument per line.\n");
367 return 1;
368}
369
370
371int main(int argc, char **argv)
372{
373 static char s_szBuf[4096];
374 static char s_szFile[1024 + sizeof(s_szBuf)];
375 int (*pfnWriter)(FILE *pOutput, const char *pszAlias, const char *pszReal);
376 char *pszFilename;
377 int i;
378 int rc;
379
380 /*
381 * Parse arguments.
382 */
383 if (argc <= 5)
384 return Syntax();
385 if (strcmp(argv[1], "-f"))
386 return SyntaxError("Expected -f as the 1st argument.\n");
387 if (!strcmp(argv[2], "aout"))
388 pfnWriter = WriteAliasObjectAOUT;
389 else if (!strcmp(argv[2], "coff"))
390 pfnWriter = WriteAliasObjectCOFF;
391 else if (!strcmp(argv[2], "elf"))
392 pfnWriter = WriteAliasObjectELF;
393 else if (!strcmp(argv[2], "omf"))
394 pfnWriter = WriteAliasObjectOMF;
395 else if (!strcmp(argv[2], "macho"))
396 pfnWriter = WriteAliasObjectMACHO;
397 else
398 return SyntaxError("Unknown format '%s'.\n", argv[2]);
399 if (strcmp(argv[3], "-D"))
400 return SyntaxError("Expected -D as the 3rd argument\n");
401 if (!*argv[4])
402 return SyntaxError("The output directory name is empty.\n");
403 size_t cchFile = strlen(argv[4]);
404 if (cchFile > sizeof(s_szFile) - sizeof(s_szBuf))
405 return SyntaxError("The output directory name is too long.\n");
406 memcpy(s_szFile, argv[4], cchFile);
407 s_szFile[cchFile++] = '/';
408 pszFilename = &s_szFile[cchFile];
409
410 /* anything to do? */
411 if (argc == 5)
412 return 0;
413
414 rc = 0;
415 if (!strcmp(argv[5], "-r"))
416 {
417 /*
418 * Responsefile.
419 */
420 FILE *pResp;
421 if (argc <= 6)
422 return SyntaxError("Missing response file name\n");
423 pResp = fopen(argv[6], "rt");
424 if (!pResp)
425 return Error("Failed to open '%s' for reading.\n", argv[6]);
426
427 i = 0;
428 while (fgets(s_szBuf, sizeof(s_szBuf), pResp))
429 {
430 size_t cch = strlen(s_szBuf);
431 i++;
432 if (cch == sizeof(s_szBuf) && s_szBuf[cch - 1] != '\n')
433 {
434 rc = Error("Line %d is too long!\n", i);
435 break;
436 }
437 if (cch && s_szBuf[cch - 1] == '\n')
438 s_szBuf[--cch] = '\0';
439 rc = CreateAlias(s_szBuf, cch, s_szFile, pszFilename, pfnWriter);
440 if (rc)
441 break;
442 }
443
444 fclose(pResp);
445 }
446 else
447 {
448 /*
449 * Alias descriptors.
450 */
451 for (i = 5; i < argc; i++)
452 {
453 size_t cch = strlen(argv[i]);
454 if (cch >= sizeof(s_szBuf))
455 return SyntaxError("Argument %d is too long\n", i);
456 memcpy(s_szBuf, argv[i], cch + 1);
457 rc = CreateAlias(s_szBuf, cch, s_szFile, pszFilename, pfnWriter);
458 if (rc)
459 break;
460 }
461 }
462 return rc;
463}
464
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette