Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

491 lines
13 KiB

  1. /*
  2. This
  3. is a place to hang .obj file munging
  4. currently it only offers the ability to do simple renaming of symbol
  5. names .obj files. It cannot lengthen symbol names.
  6. Jay Krell
  7. December 19, 2001
  8. */
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <stdlib.h>
  12. #include <ctype.h>
  13. #include "windows.h"
  14. #define NUMBER_OF(x) (sizeof(x)/sizeof((x)[0]))
  15. #define GetStdout() stdout
  16. #define GetStdin() stdin
  17. #define GetStderr() stderr
  18. void Usage(char * argv0)
  19. {
  20. char * upper;
  21. char * argv0base1;
  22. char * argv0base2;
  23. char * argv0base;
  24. argv0base1 = strrchr(argv0, '\\');
  25. argv0base2 = strrchr(argv0, '/');
  26. argv0base = (argv0base1 > argv0base2) ? argv0base1 : argv0base2;
  27. argv0base += (*argv0base == '\\' || *argv0base == '/');
  28. upper = _strdup(argv0base);
  29. if (upper != NULL)
  30. _strupr(upper);
  31. else
  32. upper = argv0;
  33. printf(
  34. "%s: usage: %s SymbolRename Objfile From To\n"
  35. "%s:\n"
  36. "%s: To must not be longer than From\n",
  37. upper, argv0, upper, upper, upper
  38. );
  39. if (upper != argv0)
  40. free(upper);
  41. }
  42. BOOL MyIsHandleValid(HANDLE Handle)
  43. {
  44. return (Handle != NULL && Handle != INVALID_HANDLE_VALUE);
  45. }
  46. void MyFindClose(HANDLE * Handle)
  47. {
  48. HANDLE Local;
  49. Local = *Handle;
  50. *Handle = NULL;
  51. if (MyIsHandleValid(Local))
  52. FindClose(Local);
  53. }
  54. void MyUnmapViewOfFile(HANDLE * Handle)
  55. {
  56. HANDLE Local;
  57. Local = *Handle;
  58. *Handle = NULL;
  59. if (MyIsHandleValid(Local))
  60. UnmapViewOfFile(Local);
  61. }
  62. void
  63. __cdecl
  64. Error(
  65. const char * Format,
  66. ...
  67. )
  68. {
  69. va_list Args;
  70. va_start(Args, Format);
  71. vfprintf(GetStderr(), Format, Args);
  72. va_end(Args);
  73. }
  74. #define Warning Error
  75. void MyCloseHandle(HANDLE * Handle)
  76. {
  77. HANDLE Local;
  78. Local = *Handle;
  79. *Handle = NULL;
  80. if (MyIsHandleValid(Local))
  81. CloseHandle(Local);
  82. }
  83. typedef struct _OBJFILE {
  84. PCSTR FileName;
  85. HANDLE FileHandle;
  86. HANDLE FileMappingHandle;
  87. PVOID VoidViewBase;
  88. PBYTE ByteViewBase;
  89. PIMAGE_FILE_HEADER ImageFileHeader;
  90. ULONG Machine;
  91. BOOL IsMachineKnown;
  92. ULONG FileOffsetToSymbolTable;
  93. PIMAGE_SYMBOL SymbolTable;
  94. ULONG NumberOfSymbols;
  95. PSTR StringTable;
  96. ULONG StringTableSize;
  97. } OBJFILE, *POBJFILE;
  98. BOOL
  99. ObjfileIsMachineKnown(
  100. ULONG Machine
  101. )
  102. {
  103. switch (Machine)
  104. {
  105. default:
  106. return FALSE;
  107. case IMAGE_FILE_MACHINE_UNKNOWN:
  108. case IMAGE_FILE_MACHINE_I386:
  109. case IMAGE_FILE_MACHINE_R3000:
  110. case IMAGE_FILE_MACHINE_R4000:
  111. case IMAGE_FILE_MACHINE_R10000:
  112. case IMAGE_FILE_MACHINE_WCEMIPSV2:
  113. case IMAGE_FILE_MACHINE_ALPHA:
  114. case IMAGE_FILE_MACHINE_SH3:
  115. case IMAGE_FILE_MACHINE_SH3DSP:
  116. case IMAGE_FILE_MACHINE_SH3E:
  117. case IMAGE_FILE_MACHINE_SH4:
  118. case IMAGE_FILE_MACHINE_SH5:
  119. case IMAGE_FILE_MACHINE_ARM:
  120. case IMAGE_FILE_MACHINE_THUMB:
  121. case IMAGE_FILE_MACHINE_AM33:
  122. case IMAGE_FILE_MACHINE_POWERPC:
  123. case IMAGE_FILE_MACHINE_POWERPCFP:
  124. case IMAGE_FILE_MACHINE_IA64:
  125. case IMAGE_FILE_MACHINE_MIPS16:
  126. case IMAGE_FILE_MACHINE_ALPHA64:
  127. case IMAGE_FILE_MACHINE_MIPSFPU:
  128. case IMAGE_FILE_MACHINE_MIPSFPU16:
  129. //case IMAGE_FILE_MACHINE_AXP64:
  130. case IMAGE_FILE_MACHINE_TRICORE:
  131. case IMAGE_FILE_MACHINE_CEF:
  132. case IMAGE_FILE_MACHINE_EBC:
  133. case IMAGE_FILE_MACHINE_AMD64:
  134. case IMAGE_FILE_MACHINE_M32R:
  135. case IMAGE_FILE_MACHINE_CEE:
  136. return TRUE;
  137. }
  138. }
  139. BOOL CloseObjfile(POBJFILE Objfile)
  140. {
  141. BOOL Success = FALSE;
  142. if (!Objfile)
  143. goto Exit;
  144. Objfile->FileName;
  145. MyCloseHandle(&Objfile->FileHandle);
  146. MyCloseHandle(&Objfile->FileMappingHandle);
  147. MyUnmapViewOfFile(&Objfile->VoidViewBase);
  148. ZeroMemory(Objfile, sizeof(*Objfile));
  149. Success = TRUE;
  150. Exit:
  151. return Success;
  152. }
  153. BOOL OpenObjfile(PCSTR FileName, POBJFILE Objfile)
  154. {
  155. const static char Function[] = __FUNCTION__;
  156. ULONG LastWin32Error;
  157. BOOL Success = FALSE;
  158. if (!FileName)
  159. goto Exit;
  160. if (!Objfile)
  161. goto Exit;
  162. Objfile->FileName = FileName;
  163. Objfile->FileHandle = CreateFile(
  164. FileName,
  165. GENERIC_READ | GENERIC_WRITE,
  166. 0,
  167. NULL,
  168. OPEN_EXISTING,
  169. FILE_ATTRIBUTE_NORMAL,
  170. NULL);
  171. if (!MyIsHandleValid(Objfile->FileHandle))
  172. {
  173. LastWin32Error = GetLastError();
  174. Error("%s: CreateFile(%s, GENERIC_WRITE, OPEN_EXISTING) 0x%lx\n", Function, FileName, LastWin32Error);
  175. goto Exit;
  176. }
  177. Objfile->FileMappingHandle = CreateFileMapping(
  178. Objfile->FileHandle, NULL, PAGE_READWRITE, 0, 0, NULL);
  179. if (!MyIsHandleValid(Objfile->FileMappingHandle))
  180. {
  181. LastWin32Error = GetLastError();
  182. Error("%s: CreateFileMapping(%s) 0x%lx\n", Function, FileName, LastWin32Error);
  183. goto Exit;
  184. }
  185. Objfile->VoidViewBase = MapViewOfFile(Objfile->FileMappingHandle, FILE_MAP_WRITE, 0, 0, 0);
  186. Objfile->ByteViewBase = (PBYTE)Objfile->VoidViewBase;
  187. if (!MyIsHandleValid(Objfile->VoidViewBase))
  188. {
  189. LastWin32Error = GetLastError();
  190. Error("%s MapViewOfFile(%s) 0x%lx\n", Function, FileName, LastWin32Error);
  191. goto Exit;
  192. }
  193. Objfile->ImageFileHeader = (PIMAGE_FILE_HEADER)Objfile->VoidViewBase;
  194. Objfile->Machine = Objfile->ImageFileHeader->Machine;
  195. Objfile->IsMachineKnown = ObjfileIsMachineKnown(Objfile->Machine);
  196. if (!Objfile->IsMachineKnown)
  197. {
  198. Warning("%s: Unknown machine 0x%lx, processing file anyway..\n", Function, Objfile->Machine);
  199. }
  200. else if (Objfile->Machine == IMAGE_FILE_MACHINE_UNKNOWN)
  201. {
  202. Error("%s: 'anon' .obj file ignored\n", Function);
  203. goto Exit;
  204. }
  205. Objfile->FileOffsetToSymbolTable = Objfile->ImageFileHeader->PointerToSymbolTable;
  206. Objfile->NumberOfSymbols = Objfile->ImageFileHeader->NumberOfSymbols;
  207. if (Objfile->FileOffsetToSymbolTable == 0)
  208. {
  209. Error("%s: file %s, PointerToSymbolTable == 0, no symbols, ignoring\n", Function, FileName);
  210. goto Exit;
  211. }
  212. if (Objfile->NumberOfSymbols == 0)
  213. {
  214. Error("%s: file %s, NumberOfSymbols == 0, no symbols, ignoring\n", Function, FileName);
  215. goto Exit;
  216. }
  217. Objfile->SymbolTable = (PIMAGE_SYMBOL)(Objfile->ByteViewBase + Objfile->FileOffsetToSymbolTable);
  218. Objfile->StringTable = (PSTR)(Objfile->SymbolTable + Objfile->NumberOfSymbols);
  219. Objfile->StringTableSize = *(PULONG)Objfile->StringTable;
  220. Success = TRUE;
  221. Exit:
  222. if (!Success)
  223. {
  224. CloseObjfile(Objfile);
  225. }
  226. return Success;
  227. }
  228. typedef struct _OBJFILE_SYMBOL {
  229. ULONG Index;
  230. PIMAGE_SYMBOL ImageSymbol;
  231. PSTR Name; /* never NULL */
  232. size_t NameLength;
  233. BOOL IsShort;
  234. ULONG UNALIGNED * PointerToOffsetToLongName; /* may be 0 */
  235. ULONG OffsetToLongName; /* may be 0 */
  236. PSTR PointerToLongNameStorage; /* may be NULL */
  237. PSTR PointerToShortNameStorage; /* never NULL */
  238. } OBJFILE_SYMBOL, *POBJFILE_SYMBOL;
  239. BOOL
  240. ObjfileResolveSymbol(
  241. POBJFILE Objfile,
  242. ULONG Index,
  243. POBJFILE_SYMBOL OutSymbol
  244. )
  245. {
  246. const static char Function[] = __FUNCTION__;
  247. BOOL Success = FALSE;
  248. OBJFILE_SYMBOL Symbol = { 0 };
  249. if (!Objfile)
  250. goto Exit;
  251. if (!OutSymbol)
  252. goto Exit;
  253. *OutSymbol = Symbol;
  254. if (Index >= Objfile->NumberOfSymbols)
  255. {
  256. Warning("%s: file %s, SymbolIndex >= NumberOfSymbols (0x%lx, 0x%lx)\n",
  257. Function,
  258. Objfile->FileName,
  259. Index,
  260. Objfile->NumberOfSymbols
  261. );
  262. goto Exit;
  263. }
  264. Symbol.Index = Index;
  265. Symbol.ImageSymbol = &Objfile->SymbolTable[Index];
  266. Symbol.PointerToShortNameStorage = (PSTR)Symbol.ImageSymbol->N.ShortName;
  267. if (Symbol.ImageSymbol->N.Name.Short)
  268. {
  269. for ( ;
  270. Symbol.NameLength != IMAGE_SIZEOF_SHORT_NAME ;
  271. ++Symbol.NameLength
  272. )
  273. {
  274. if (Symbol.PointerToShortNameStorage[Symbol.NameLength] == 0)
  275. break;
  276. }
  277. Symbol.Name = Symbol.PointerToShortNameStorage;
  278. Symbol.IsShort = TRUE;
  279. }
  280. else
  281. {
  282. Symbol.PointerToOffsetToLongName = &Symbol.ImageSymbol->N.Name.Long;
  283. Symbol.OffsetToLongName = *Symbol.PointerToOffsetToLongName;
  284. if (Symbol.OffsetToLongName >= Objfile->StringTableSize)
  285. {
  286. Warning("%s: file %s, OffsetToLongName >= StringTableSize (0x%lx, 0x%lx)\n",
  287. Function,
  288. Objfile->FileName,
  289. Symbol.OffsetToLongName,
  290. Objfile->StringTableSize
  291. );
  292. goto Exit;
  293. }
  294. Symbol.Name = (Objfile->StringTable + Symbol.OffsetToLongName);
  295. Symbol.PointerToLongNameStorage = Symbol.Name;
  296. Symbol.NameLength = strlen(Symbol.Name);
  297. }
  298. *OutSymbol = Symbol;
  299. Success = TRUE;
  300. Exit:
  301. return Success;
  302. }
  303. BOOL
  304. ObjfileSetSymbolName(
  305. POBJFILE Objfile,
  306. POBJFILE_SYMBOL Symbol,
  307. PCSTR NewSymbolName
  308. )
  309. {
  310. const static char Function[] = __FUNCTION__;
  311. PIMAGE_SYMBOL ImageSymbol;
  312. size_t i;
  313. BOOL Success = FALSE;
  314. if (!Objfile)
  315. goto Exit;
  316. if (!Symbol)
  317. goto Exit;
  318. if (!NewSymbolName)
  319. goto Exit;
  320. ImageSymbol = Symbol->ImageSymbol;
  321. i = strlen(NewSymbolName);
  322. if (i <= IMAGE_SIZEOF_SHORT_NAME)
  323. {
  324. //
  325. // we abandon the string table entry if there was one.
  326. //
  327. memmove(Symbol->PointerToShortNameStorage, NewSymbolName, i);
  328. ZeroMemory(Symbol->PointerToShortNameStorage + i, IMAGE_SIZEOF_SHORT_NAME - i);
  329. }
  330. else if (!Symbol->IsShort && i <= Symbol->NameLength)
  331. {
  332. //
  333. // like
  334. // \0\reallylonglonglong\0
  335. // -> \0\lesslonglong\0long\0
  336. //
  337. memmove(Symbol->PointerToLongNameStorage, NewSymbolName, i);
  338. Symbol->PointerToLongNameStorage[i] = 0;
  339. }
  340. else
  341. {
  342. Warning("%s: objfile %s, new symbol does not fit over old symbol (%s, %*s)\n",
  343. Function,
  344. Objfile->FileName,
  345. NewSymbolName,
  346. (int)Symbol->NameLength,
  347. Symbol->Name
  348. );
  349. goto Exit;
  350. }
  351. Success = TRUE;
  352. Exit:
  353. return Success;
  354. }
  355. BOOL
  356. SymbolRename(
  357. PCSTR ObjfileName,
  358. PCSTR From,
  359. PCSTR To,
  360. PULONG NumberFound
  361. )
  362. {
  363. const static char Function[] = __FUNCTION__;
  364. OBJFILE Objfile = { 0 };
  365. ULONG SymbolIndex;
  366. OBJFILE_SYMBOL Symbol = { 0 };
  367. size_t FromLength;
  368. BOOL Success = FALSE;
  369. if (NumberFound == NULL)
  370. goto Exit;
  371. *NumberFound = 0;
  372. if (!OpenObjfile(ObjfileName, &Objfile))
  373. goto Exit;
  374. FromLength = strlen(From);
  375. for ( SymbolIndex = 0 ;
  376. SymbolIndex != Objfile.NumberOfSymbols ;
  377. SymbolIndex += 1 + Symbol.ImageSymbol->NumberOfAuxSymbols
  378. )
  379. {
  380. if (!ObjfileResolveSymbol(&Objfile, SymbolIndex, &Symbol))
  381. goto Exit;
  382. if (FromLength == Symbol.NameLength
  383. && memcmp(From, Symbol.Name, FromLength) == 0)
  384. {
  385. if (*NumberFound != 0)
  386. {
  387. Warning("%s: objfile %s, multiple symbols with same name found (%s)\n",
  388. Function,
  389. Objfile.FileName,
  390. From
  391. );
  392. }
  393. *NumberFound += 1;
  394. if (!ObjfileSetSymbolName(&Objfile, &Symbol, To))
  395. goto Exit;
  396. }
  397. }
  398. Success = TRUE;
  399. Exit:
  400. CloseObjfile(&Objfile);
  401. return Success;
  402. }
  403. void Objtool(int argc, char ** argv)
  404. {
  405. const static char Function[] = __FUNCTION__;
  406. PCSTR From;
  407. PCSTR To;
  408. PCSTR ObjfileName;
  409. ULONG NumberFound = 0;
  410. int i;
  411. const char * symren[] =
  412. { "symren", "symrename", "symbolrename", "symbolren" };
  413. if (argc < 2)
  414. {
  415. Usage(argv[0]);
  416. return;
  417. }
  418. argv[1] += (argv[1][0] == '-' || argv[1][0] == '/');
  419. for (i = 0 ; i != NUMBER_OF(symren) ; ++i)
  420. {
  421. if (_stricmp(argv[1], symren[i]) == 0)
  422. {
  423. if (
  424. (ObjfileName = argv[2]) == NULL
  425. || (From = argv[3]) == NULL
  426. || (To = argv[4]) == NULL
  427. || strlen(To) > strlen(From)
  428. )
  429. {
  430. Usage(argv[0]);
  431. return;
  432. }
  433. SymbolRename(ObjfileName, From, To, &NumberFound);
  434. return;
  435. }
  436. }
  437. Usage(argv[0]);
  438. }
  439. int __cdecl main(int argc, char ** argv)
  440. {
  441. Objtool(argc, argv);
  442. return 0;
  443. }