VirtualBox

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

Last change on this file since 106724 was 106061, checked in by vboxsync, 2 months ago

Copyright year updates by scm.

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