00001
00007 #include "objectFile.h"
00008 #include "hashmap.h"
00009 #include "graph.h"
00010
00011 #include <stdlib.h>
00012 #include <string.h>
00013 #include <ctype.h>
00014
00015
00016
00017 #define SO_FOUNDNAME 1
00018 #define SO_FOUNDSECTION 2
00019
00020 #define SO_PREFIX_COUNT (sizeof(prefix)/sizeof(char*))
00021 #define SO_WEAK_COUNT (sizeof(weak)/sizeof(char*))
00022
00023 static const char* prefix[] =
00024 { ".text$", ".rdata$", ".data$" };
00025 static const char* weak[] =
00026 { ".rdata" };
00027
00028 static hashmap* sectionMap = 0;
00029 static list* unknownSection = 0;
00030
00033 struct s_objectFile
00034 {
00035 const char* name;
00036 list* sects;
00037 };
00038
00039
00040
00045 static char* trim(char* src)
00046 {
00047 while (isspace(*src))
00048 ++src;
00049 return src;
00050 }
00051
00055 static void upper(char* src)
00056 {
00057 while (*src)
00058 {
00059 *src = toupper(*src);
00060 ++src;
00061 }
00062 }
00063
00068 static void parseRelocSection(graph* src, FILE* file)
00069 {
00070 static char buffer[256];
00071 char *ptr, *token;
00072
00073 while (!feof(file))
00074 {
00075 fgets(buffer, sizeof(buffer), file);
00076 ptr = trim(buffer);
00077
00078
00079
00080 if (!*ptr)
00081 return;
00082
00083
00084 token = strtok(ptr, " ");
00085
00086 token = strtok(0, " ");
00087
00088
00089
00090 token = strtok(0, " ");
00091
00092 if (token)
00093 {
00094 graph* dest;
00095
00096
00097
00098 if (*token == '_')
00099 ++token;
00100
00101 else if (*token == '@')
00102 {
00103 ++token;
00104 token = strtok(token, "@");
00105 }
00106
00107 else
00108 {
00109 int i = SO_PREFIX_COUNT;
00110
00111 while (i--)
00112 if (!strncmp(token, prefix[i], strlen(prefix[i])))
00113 {
00114 token += strlen(prefix[i]);
00115 break;
00116 }
00117 }
00118
00119
00120 {
00121 char* i = token + strlen(token);
00122 while (isspace(*--i));
00123
00124 i[1] = 0;
00125
00126
00127
00128 while (isdigit(*--i));
00129
00130 if (*i == '@')
00131 *i = 0;
00132 }
00133
00134 dest = (graph*) hashmapGet(sectionMap, token);
00135
00136 if (dest)
00137 {
00138
00139 if (src)
00140 graphConnect(src, dest);
00141
00142
00143
00144
00145 else
00146 listAdd(unknownSection, dest);
00147 }
00148 }
00149 }
00150 }
00151
00156 static void colorizeGraph(graph* seed, unsigned long color)
00157 {
00158 unsigned long c = graphGetColorNode(seed);
00159 if ((c | color) != c)
00160 {
00161 list* depends = graphGetConnections(seed);
00162 graphColorNode(seed, c | color);
00163
00164 listStart(depends);
00165 while (listNext(depends))
00166 colorizeGraph((graph*) listGet(depends), color);
00167 }
00168 }
00169
00170
00171
00172 objectFile* objectFileCreate(const char* name)
00173 {
00174 objectFile* res = (objectFile*) malloc(sizeof(objectFile));
00175
00176 res->name = name;
00177 res->sects = newList();
00178
00179 return res;
00180 }
00181
00182 void objectFileCollect(objectFile* src, FILE* file)
00183 {
00184 unsigned long progress = 0;
00185 char buffer[256], *ptr, *token;
00186
00187 while (!feof(file))
00188 {
00189 fgets(buffer, sizeof(buffer), file);
00190 ptr = trim(buffer);
00191
00192 if (*ptr)
00193 {
00194 switch (progress)
00195 {
00196 case 0:
00197 token = strtok(ptr, ":");
00198 if (token && !strcmp(token, src->name))
00199 progress = SO_FOUNDNAME;
00200 break;
00201
00202
00203 case SO_FOUNDNAME:
00204 token = strtok(ptr, ":");
00205 if (token)
00206 {
00207 upper(token);
00208 if (!strcmp(token, "SECTIONS"))
00209 {
00210 fgets(buffer, sizeof(buffer), file);
00211 progress = SO_FOUNDSECTION;
00212 }
00213 }
00214 break;
00215
00216
00217 case SO_FOUNDSECTION:
00218 token = strtok(ptr, " ");
00219
00220 if (token)
00221 {
00222 token = strtok(0, " ");
00223 if (token)
00224 {
00225 int i = SO_PREFIX_COUNT;
00226
00227
00228
00229 while (i--)
00230 if (!strncmp(token, prefix[i], strlen(prefix[i])))
00231 {
00232 listAdd(src->sects, strdup(token));
00233 break;
00234 }
00235 }
00236 }
00237 }
00238 }
00239
00240 else if (progress == SO_FOUNDSECTION)
00241 return;
00242 }
00243 }
00244
00245 void objectFileCompute(list* oFiles, FILE* file)
00246 {
00247 objectFile* cFile;
00248
00249
00250 if (sectionMap)
00251 deleteHashmap(sectionMap);
00252 if (unknownSection)
00253 deleteList(unknownSection);
00254
00255 sectionMap = newHashmap(8);
00256 unknownSection = newList();
00257
00258
00259
00260 listStart(oFiles);
00261 while (listNext(oFiles))
00262 {
00263 cFile = (objectFile*) listGet(oFiles);
00264 if (!listIsEmpty(cFile->sects))
00265 {
00266 listStart(cFile->sects);
00267 while (listNext(cFile->sects))
00268 {
00269 char *token, *ptr;
00270 int i = SO_PREFIX_COUNT;
00271 ptr = token = (char*) listGet(cFile->sects);
00272
00273
00274
00275 while (i--)
00276 if (!strncmp(token, prefix[i], strlen(prefix[i])))
00277 {
00278 ptr += strlen(prefix[i]);
00279 listSet(cFile->sects, ptr);
00280 break;
00281 }
00282
00283
00284 if (!hashmapGet(sectionMap, ptr))
00285 hashmapSet(sectionMap, newGraph(token), ptr);
00286 }
00287 }
00288 }
00289
00290
00291 {
00292 char buffer[256], *ptr, *token;
00293 graph* cGraph;
00294
00295 while (!feof(file))
00296 {
00297 ParseLoop: fgets(buffer, sizeof(buffer), file);
00298 ptr = trim(buffer);
00299
00300 if (*ptr)
00301 {
00302 token = strtok(ptr, ":");
00303 if (token)
00304 {
00305
00306 if (!strncmp(token, "RELOCATION", sizeof("RELOCATION") - 1))
00307 {
00308 int i;
00309
00310
00311 token += sizeof("RELOCATION");
00312 while (*token && *token++ != '[');
00313
00314
00315 if (!*token)
00316 {
00317 fprintf(stderr, "ERROR: file with relocation table "
00318 "has invalid format!\n");
00319 return;
00320 }
00321
00322
00323
00324 i = SO_PREFIX_COUNT;
00325 while (i--)
00326 if (!strncmp(token, prefix[i], strlen(prefix[i])))
00327 {
00328 token += strlen(prefix[i]);
00329 break;
00330 }
00331
00332 token = strtok(token, "]");
00333
00334
00335
00336 if (!token)
00337 {
00338 fprintf(stderr, "ERROR: file with relocation table "
00339 "has invalid format!\n");
00340 return;
00341 }
00342
00343 cGraph = (graph*) hashmapGet(sectionMap, token);
00344
00345 if (!cGraph)
00346 {
00347
00348 i = SO_WEAK_COUNT;
00349 while (i--)
00350 if (!strcmp(token, weak[i]))
00351 goto ParseLoop;
00352 }
00353
00354
00355 fgets(buffer, sizeof(buffer), file);
00356
00357 parseRelocSection(cGraph, file);
00358 }
00359 }
00360 }
00361 }
00362 }
00363
00364
00365
00366
00367
00368
00369
00370
00371 listStart(unknownSection);
00372 while (listNext(unknownSection))
00373 colorizeGraph((graph*) listGet(unknownSection), 0x80000000);
00374 }
00375
00376 void objectFileColorize(const char* seed, unsigned long color)
00377 {
00378 graph* start = (graph*) hashmapGet(sectionMap, seed);
00379
00380 if (start)
00381 colorizeGraph(start, color);
00382 }
00383
00384 list* objectFileGetUsed(objectFile* src)
00385 {
00386 list* res = newList();
00387
00388 listStart(src->sects);
00389 while (listNext(src->sects))
00390 {
00391 char* name = (char*) listGet(src->sects);
00392 graph* curr = (graph*) hashmapGet(sectionMap, name);
00393
00394 if (graphGetColorNode(curr))
00395 listAdd(res, graphGetNameNode(curr));
00396 }
00397
00398 return res;
00399 }
00400
00401 list* objectFileGetUnused(objectFile* src)
00402 {
00403 list* res = newList();
00404
00405 listStart(src->sects);
00406 while (listNext(src->sects))
00407 {
00408 char* name = (char*) listGet(src->sects);
00409 graph* curr = (graph*) hashmapGet(sectionMap, name);
00410
00411 if (!graphGetColorNode(curr))
00412 listAdd(res, graphGetNameNode(curr));
00413 }
00414
00415 return res;
00416 }
00417
00418 const char* objectFileGetName(objectFile* src)
00419 {
00420 return src->name;
00421 }
00422
00423 void objectFileDumpMap(list* oFiles)
00424 {
00425
00426 printf("\n<MAP>\n");
00427 listStart(oFiles);
00428 while (listNext(oFiles))
00429 {
00430 objectFile* oFile = (objectFile*) listGet(oFiles);
00431 printf("\t<FILE name=\"%s\">\n", oFile->name);
00432 fflush(stdout);
00433
00434 listStart(oFile->sects);
00435 while (listNext(oFile->sects))
00436 {
00437 char* name = (char*) listGet(oFile->sects);
00438 graph* sect = (graph*) hashmapGet(sectionMap, name);
00439 list* depend = graphGetConnections(sect);
00440
00441 printf("\t\t<SECTION name=\"%s\" color=%lu>\n",
00442 (char*) graphGetNameNode(sect), graphGetColorNode(sect));
00443 fflush(stdout);
00444
00445 listStart(depend);
00446 while (listNext(depend))
00447 {
00448 graph* d = (graph*) listGet(depend);
00449 printf("\t\t\t<DEPENDS>%s</DEPENDS>\n", (char*) graphGetNameNode(d));
00450 fflush(stdout);
00451 }
00452
00453 printf("\t\t</SECTION>\n");
00454 fflush(stdout);
00455 }
00456 printf("\t</FILE>\n");
00457 fflush(stdout);
00458 }
00459 printf("\n</MAP>\n");
00460 fflush(stdout);
00461 }
00462
00463 void objectFileDumpUsed(list* oFiles)
00464 {
00465 printf("\n<USED>\n");
00466
00467 listStart(oFiles);
00468 while (listNext(oFiles))
00469 {
00470 objectFile* obj = (objectFile*) listGet(oFiles);
00471 list* curr = objectFileGetUsed(obj);
00472
00473 printf("\t<FILE name=\"%s\">\n", obj->name);
00474
00475 listStart(curr);
00476 while (listNext(curr))
00477 printf("\t\t<SECTION>%s</SECTION>\n", (char*) listGet(curr));
00478
00479 deleteList(curr);
00480
00481 printf("\t</FILE>\n");
00482 }
00483 printf("</USED>\n");
00484 }
00485
00486 void objectFileDumpUnused(list* oFiles)
00487 {
00488 printf("\n<UNUSED>\n");
00489
00490 listStart(oFiles);
00491 while (listNext(oFiles))
00492 {
00493 objectFile* obj = (objectFile*) listGet(oFiles);
00494 list* curr = objectFileGetUnused(obj);
00495
00496 printf("\t<FILE name=\"%s\">\n", obj->name);
00497
00498 listStart(curr);
00499 while (listNext(curr))
00500 printf("\t\t<SECTION>%s</SECTION>\n", (char*) listGet(curr));
00501
00502 deleteList(curr);
00503
00504 printf("\t</FILE>\n");
00505 }
00506 printf("</UNUSED>\n");
00507 }