├── LICENSE ├── Makefile.am ├── NidMgr.C ├── NidMgr.h ├── ProcessElf.C ├── ProcessElf.h ├── ProcessPrx.C ├── ProcessPrx.h ├── README.md ├── SerializePrx.C ├── SerializePrx.h ├── SerializePrxToIdc.C ├── SerializePrxToIdc.h ├── SerializePrxToMap.C ├── SerializePrxToMap.h ├── SerializePrxToXml.C ├── SerializePrxToXml.h ├── VirtualMem.C ├── VirtualMem.h ├── aclocal ├── ax_create_stdint_h.m4 └── version.m4 ├── bootstrap ├── configure.ac ├── disasm.C ├── disasm.h ├── elftypes.h ├── functions.txt ├── getargs.C ├── getargs.h ├── main.C ├── output.C ├── output.h ├── prxtypes.h ├── pspkerror.C ├── pspkerror.h ├── tinyxml ├── VERSION ├── changes.txt ├── readme.txt ├── tinystr.cpp ├── tinystr.h ├── tinyxml.cpp ├── tinyxml.h ├── tinyxmlerror.cpp └── tinyxmlparser.cpp └── types.h /LICENSE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balika011/prxtool/fc444dd751f30132c971c832a619d60b5420e321/LICENSE -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | ACLOCAL_AMFLAGS = -I aclocal 2 | ACLOCAL_FILES = aclocal/version.m4 aclocal/ax_create_stdint_h.m4 3 | AM_CFLAGS = -Wall 4 | 5 | bin_PROGRAMS = prxtool 6 | 7 | TINYXML = $(srcdir)/tinyxml 8 | INLCUDES = -I $(srcdir) -I $(TINYXML) 9 | 10 | LIBS = -lcapstone -ljansson 11 | 12 | prxtool_SOURCES = \ 13 | main.C \ 14 | ProcessElf.C \ 15 | ProcessPrx.C \ 16 | NidMgr.C \ 17 | VirtualMem.C \ 18 | output.C \ 19 | SerializePrx.C \ 20 | SerializePrxToIdc.C \ 21 | SerializePrxToXml.C \ 22 | SerializePrxToMap.C \ 23 | pspkerror.C \ 24 | disasm.C \ 25 | getargs.C \ 26 | $(TINYXML)/tinyxml.cpp \ 27 | $(TINYXML)/tinyxmlparser.cpp \ 28 | $(TINYXML)/tinystr.cpp \ 29 | $(TINYXML)/tinyxmlerror.cpp 30 | 31 | noinst_HEADERS = \ 32 | types.h \ 33 | elftypes.h \ 34 | prxtypes.h \ 35 | output.h \ 36 | NidMgr.h \ 37 | ProcessElf.h \ 38 | ProcessPrx.h \ 39 | SerializePrx.h \ 40 | SerializePrxToIdc.h \ 41 | SerializePrxToXml.h \ 42 | SerializePrxToMap.h \ 43 | VirtualMem.h \ 44 | pspkerror.h \ 45 | disasm.h \ 46 | getargs.h \ 47 | $(TINYXML)/tinystr.h \ 48 | $(TINYXML)/tinyxml.h 49 | 50 | EXTRA_DIST = \ 51 | $(ACLOCAL_FILES) \ 52 | LICENSE \ 53 | $(TINYXML)/VERSION \ 54 | $(TINYXML)/changes.txt \ 55 | $(TINYXML)/readme.txt 56 | 57 | DISTCLEANFILES = _stdint.h 58 | -------------------------------------------------------------------------------- /NidMgr.C: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | * PRXTool : Utility for PSP executables. 3 | * (c) TyRaNiD 2k5 4 | * 5 | * NidMgr.C - Implementation of a class to manipulate a list 6 | * of NID Libraries. 7 | ***************************************************************/ 8 | 9 | #include 10 | #include 11 | #include 12 | #include "output.h" 13 | #include "NidMgr.h" 14 | #include "prxtypes.h" 15 | 16 | struct SyslibEntry 17 | { 18 | unsigned int nid; 19 | const char *name; 20 | }; 21 | 22 | static SyslibEntry g_syslib[] = { 23 | { 0x70FBA1E7, "module_process_param" }, 24 | { 0x6C2224BA, "module_info" }, 25 | { 0x935CD196, "module_start" }, 26 | { 0x79F8E492, "module_stop" }, 27 | { 0x913482A9, "module_exit" }, 28 | }; 29 | 30 | #define MASTER_NID_MAPPER "MasterNidMapper" 31 | 32 | /* Default constructor */ 33 | CNidMgr::CNidMgr() 34 | : m_pLibHead(NULL), m_pMasterNids(NULL) 35 | { 36 | } 37 | 38 | /* Destructor */ 39 | CNidMgr::~CNidMgr() 40 | { 41 | FreeMemory(); 42 | } 43 | 44 | /* Free allocated memory */ 45 | void CNidMgr::FreeMemory() 46 | { 47 | LibraryEntry* pLib; 48 | 49 | pLib = m_pLibHead; 50 | while(pLib != NULL) 51 | { 52 | LibraryEntry* pNext; 53 | 54 | pNext = pLib->pNext; 55 | 56 | if(pLib->pNids != NULL) 57 | { 58 | delete pLib->pNids; 59 | pLib->pNids = NULL; 60 | } 61 | 62 | delete pLib; 63 | pLib = pNext; 64 | } 65 | 66 | m_pLibHead = NULL; 67 | 68 | for(unsigned int i = 0; i < m_funcMap.size(); i++) 69 | { 70 | FunctionType *p; 71 | p = m_funcMap[i]; 72 | if(p) 73 | { 74 | delete p; 75 | } 76 | } 77 | } 78 | 79 | /* Generate a simple name based on the library and the nid */ 80 | const char *CNidMgr::GenName(const char *lib, u32 nid) 81 | { 82 | if(lib == NULL) 83 | { 84 | snprintf(m_szCurrName, LIB_SYMBOL_NAME_MAX, "syslib_%08X", nid); 85 | } 86 | else 87 | { 88 | snprintf(m_szCurrName, LIB_SYMBOL_NAME_MAX, "%s_%08X", lib, nid); 89 | } 90 | 91 | return m_szCurrName; 92 | } 93 | 94 | /* Search the NID list for a function and return the name */ 95 | const char *CNidMgr::SearchLibs(const char *lib, u32 nid) 96 | { 97 | const char *pName = NULL; 98 | LibraryEntry *pLib; 99 | 100 | if(m_pMasterNids) 101 | { 102 | pLib = m_pMasterNids; 103 | } 104 | else 105 | { 106 | pLib = m_pLibHead; 107 | } 108 | 109 | /* Very lazy, could be sped up using a hash table */ 110 | while(pLib != NULL) 111 | { 112 | if((strcmp(lib, pLib->lib_name) == 0) || (m_pMasterNids)) 113 | { 114 | int iNidLoop; 115 | 116 | for(iNidLoop = 0; iNidLoop < pLib->entry_count; iNidLoop++) 117 | { 118 | if(pLib->pNids[iNidLoop].nid == nid) 119 | { 120 | pName = pLib->pNids[iNidLoop].name; 121 | COutput::Printf(LEVEL_DEBUG, "Using %s, nid %08X\n", pName, nid); 122 | break; 123 | } 124 | } 125 | 126 | if(pName != NULL) 127 | { 128 | break; 129 | } 130 | } 131 | 132 | if(m_pMasterNids) 133 | { 134 | pLib = NULL; 135 | } 136 | else 137 | { 138 | pLib = pLib->pNext; 139 | } 140 | } 141 | 142 | if(pName == NULL) 143 | { 144 | /* First check special case system library stuff */ 145 | if(strcmp(lib, PSP_SYSTEM_EXPORT) == 0) 146 | { 147 | int size; 148 | int i; 149 | 150 | size = sizeof(g_syslib) / sizeof(SyslibEntry); 151 | for(i = 0; i < size; i++) 152 | { 153 | if(nid == g_syslib[i].nid) 154 | { 155 | pName = g_syslib[i].name; 156 | break; 157 | } 158 | } 159 | } 160 | 161 | if(pName == NULL) 162 | { 163 | COutput::Puts(LEVEL_DEBUG, "Using default name"); 164 | pName = GenName(lib, nid); 165 | } 166 | } 167 | 168 | return pName; 169 | } 170 | 171 | /* Read the NID data from the XML file */ 172 | const char* CNidMgr::ReadNid(TiXmlElement *pElement, u32 &nid) 173 | { 174 | TiXmlHandle nidHandle(pElement); 175 | TiXmlText *pNid; 176 | TiXmlText *pName; 177 | const char* szName; 178 | 179 | szName = NULL; 180 | pNid = nidHandle.FirstChild("NID").FirstChild().Text(); 181 | pName = nidHandle.FirstChild("NAME").FirstChild().Text(); 182 | 183 | if((pNid != NULL) && (pName != NULL)) 184 | { 185 | nid = strtoul(pNid->Value(), NULL, 16); 186 | szName = pName->Value(); 187 | } 188 | 189 | return szName; 190 | } 191 | 192 | /* Count the number of nids in the current element */ 193 | int CNidMgr::CountNids(TiXmlElement *pElement, const char *name) 194 | { 195 | TiXmlElement *pIterator; 196 | u32 nid; 197 | int iCount = 0; 198 | 199 | pIterator = pElement; 200 | while(pIterator != NULL) 201 | { 202 | if(ReadNid(pIterator, nid) != NULL) 203 | { 204 | iCount++; 205 | } 206 | pIterator = pIterator->NextSiblingElement(name); 207 | } 208 | 209 | return iCount; 210 | } 211 | 212 | /* Process a library XML element */ 213 | void CNidMgr::ProcessLibrary(TiXmlElement *pLibrary, const char *prx_name, const char *prx) 214 | { 215 | TiXmlHandle libHandle(pLibrary); 216 | TiXmlText *elmName; 217 | TiXmlText *elmFlags; 218 | TiXmlElement *elmFunction; 219 | TiXmlElement *elmVariable; 220 | int fCount; 221 | int vCount; 222 | bool blMasterNids = false; 223 | 224 | assert(prx_name != NULL); 225 | assert(prx != NULL); 226 | 227 | elmName = libHandle.FirstChild("NAME").FirstChild().Text(); 228 | elmFlags = libHandle.FirstChild("FLAGS").FirstChild().Text(); 229 | if(elmName) 230 | { 231 | LibraryEntry *pLib; 232 | 233 | COutput::Printf(LEVEL_DEBUG, "Library %s\n", elmName->Value()); 234 | SAFE_ALLOC(pLib, LibraryEntry); 235 | if(pLib != NULL) 236 | { 237 | memset(pLib, 0, sizeof(LibraryEntry)); 238 | strcpy(pLib->lib_name, elmName->Value()); 239 | if(strcmp(pLib->lib_name, MASTER_NID_MAPPER) == 0) 240 | { 241 | blMasterNids = true; 242 | COutput::Printf(LEVEL_DEBUG, "Found master NID table\n"); 243 | } 244 | 245 | if(elmFlags) 246 | { 247 | pLib->flags = strtoul(elmFlags->Value(), NULL, 16); 248 | } 249 | 250 | strcpy(pLib->prx_name, prx_name); 251 | strcpy(pLib->prx, prx); 252 | elmFunction = libHandle.FirstChild("FUNCTIONS").FirstChild("FUNCTION").Element(); 253 | elmVariable = libHandle.FirstChild("VARIABLES").FirstChild("VARIABLE").Element(); 254 | fCount = CountNids(elmFunction, "FUNCTION"); 255 | vCount = CountNids(elmVariable, "VARIABLE"); 256 | pLib->vcount = vCount; 257 | pLib->fcount = fCount; 258 | if((fCount+vCount) > 0) 259 | { 260 | SAFE_ALLOC(pLib->pNids, LibraryNid[vCount+fCount]); 261 | if(pLib->pNids != NULL) 262 | { 263 | int iLoop; 264 | const char *pName; 265 | 266 | memset(pLib->pNids, 0, sizeof(LibraryNid) * (vCount+fCount)); 267 | pLib->entry_count = vCount + fCount; 268 | iLoop = 0; 269 | while(elmFunction != NULL) 270 | { 271 | pName = ReadNid(elmFunction, pLib->pNids[iLoop].nid); 272 | if(pName) 273 | { 274 | pLib->pNids[iLoop].pParentLib = pLib; 275 | strcpy(pLib->pNids[iLoop].name, pName); 276 | COutput::Printf(LEVEL_DEBUG, "Read func:%s nid:0x%08X\n", pLib->pNids[iLoop].name, pLib->pNids[iLoop].nid); 277 | iLoop++; 278 | } 279 | 280 | elmFunction = elmFunction->NextSiblingElement("FUNCTION"); 281 | } 282 | 283 | while(elmVariable != NULL) 284 | { 285 | pName = ReadNid(elmVariable, pLib->pNids[iLoop].nid); 286 | if(pName) 287 | { 288 | strcpy(pLib->pNids[iLoop].name, pName); 289 | COutput::Printf(LEVEL_DEBUG, "Read var:%s nid:0x%08X\n", pLib->pNids[iLoop].name, pLib->pNids[iLoop].nid); 290 | iLoop++; 291 | } 292 | 293 | elmVariable = elmVariable->NextSiblingElement("VARIABLE"); 294 | } 295 | } 296 | } 297 | 298 | /* Link into list */ 299 | if(m_pLibHead == NULL) 300 | { 301 | m_pLibHead = pLib; 302 | } 303 | else 304 | { 305 | pLib->pNext = m_pLibHead; 306 | m_pLibHead = pLib; 307 | } 308 | 309 | if(blMasterNids) 310 | { 311 | m_pMasterNids = pLib; 312 | } 313 | } 314 | 315 | /* Allocate library memory */ 316 | } 317 | } 318 | 319 | /* Process a PRXFILE XML element */ 320 | void CNidMgr::ProcessPrxfile(TiXmlElement *pPrxfile) 321 | { 322 | TiXmlHandle prxHandle(pPrxfile); 323 | TiXmlElement *elmLibrary; 324 | TiXmlText *txtName; 325 | TiXmlText *txtPrx; 326 | const char *szPrx; 327 | 328 | txtPrx = prxHandle.FirstChild("PRX").FirstChild().Text(); 329 | txtName = prxHandle.FirstChild("PRXNAME").FirstChild().Text(); 330 | 331 | elmLibrary = prxHandle.FirstChild("LIBRARIES").FirstChild("LIBRARY").Element(); 332 | while(elmLibrary) 333 | { 334 | COutput::Puts(LEVEL_DEBUG, "Found LIBRARY"); 335 | 336 | if(txtPrx == NULL) 337 | { 338 | szPrx = "unknown.prx"; 339 | } 340 | else 341 | { 342 | szPrx = txtPrx->Value(); 343 | } 344 | 345 | if(txtName != NULL) 346 | { 347 | ProcessLibrary(elmLibrary, txtName->Value(), szPrx); 348 | } 349 | 350 | elmLibrary = elmLibrary->NextSiblingElement("LIBRARY"); 351 | } 352 | } 353 | 354 | /* Add an XML file to the current library list */ 355 | bool CNidMgr::AddXmlFile(const char *szFilename) 356 | { 357 | TiXmlDocument doc(szFilename); 358 | bool blRet = false; 359 | 360 | if(doc.LoadFile()) 361 | { 362 | COutput::Printf(LEVEL_DEBUG, "Loaded XML file %s", szFilename); 363 | TiXmlHandle docHandle(&doc); 364 | TiXmlElement *elmPrxfile; 365 | 366 | elmPrxfile = docHandle.FirstChild("PSPLIBDOC").FirstChild("PRXFILES").FirstChild("PRXFILE").Element(); 367 | while(elmPrxfile) 368 | { 369 | COutput::Puts(LEVEL_DEBUG, "Found PRXFILE"); 370 | ProcessPrxfile(elmPrxfile); 371 | 372 | elmPrxfile = elmPrxfile->NextSiblingElement("PRXFILE"); 373 | } 374 | blRet = true; 375 | } 376 | else 377 | { 378 | COutput::Printf(LEVEL_ERROR, "Couldn't load xml file %s\n", szFilename); 379 | } 380 | 381 | return blRet; 382 | } 383 | 384 | int CNidMgr::vita_imports_loads(FILE *text, int verbose) 385 | { 386 | bool blMasterNids = false; 387 | 388 | json_t *libs, *lib_data; 389 | json_error_t error; 390 | const char *lib_name, *mod_name, *target_name; 391 | 392 | libs = json_loadf(text, 0, &error); 393 | if (libs == NULL) { 394 | COutput::Printf(LEVEL_ERROR, "error: on line %d: %s\n", error.line, error.text); 395 | return 0; 396 | } 397 | 398 | if (!json_is_object(libs)) { 399 | COutput::Printf(LEVEL_ERROR, "error: modules is not an object\n"); 400 | json_decref(libs); 401 | return 0; 402 | } 403 | 404 | int i, j, k; 405 | 406 | i = -1; 407 | json_object_foreach(libs, lib_name, lib_data) { 408 | json_t *nid, *modules, *mod_data; 409 | 410 | i++; 411 | 412 | if (!json_is_object(lib_data)) { 413 | COutput::Printf(LEVEL_ERROR, "error: library %s is not an object\n", lib_name); 414 | json_decref(libs); 415 | return 0; 416 | } 417 | 418 | nid = json_object_get(lib_data, "nid"); 419 | if (!json_is_integer(nid)) { 420 | COutput::Printf(LEVEL_ERROR, "error: library %s: nid is not an integer\n", lib_name); 421 | json_decref(libs); 422 | return 0; 423 | } 424 | 425 | modules = json_object_get(lib_data, "modules"); 426 | if (!json_is_object(modules)) { 427 | COutput::Printf(LEVEL_ERROR, "error: library %s: module is not an object\n", lib_name); 428 | json_decref(libs); 429 | return 0; 430 | } 431 | 432 | j = -1; 433 | json_object_foreach(modules, mod_name, mod_data) { 434 | json_t *nid, *kernel, *functions, *variables, *target_nid; 435 | int has_variables = 1; 436 | 437 | j++; 438 | 439 | if (!json_is_object(mod_data)) { 440 | COutput::Printf(LEVEL_ERROR, "error: module %s is not an object\n", mod_name); 441 | json_decref(libs); 442 | return 0; 443 | } 444 | 445 | nid = json_object_get(mod_data, "nid"); 446 | if (!json_is_integer(nid)) { 447 | COutput::Printf(LEVEL_ERROR, "error: module %s: nid is not an integer\n", mod_name); 448 | json_decref(libs); 449 | return 0; 450 | } 451 | 452 | kernel = json_object_get(mod_data, "kernel"); 453 | if (!json_is_boolean(kernel)) { 454 | COutput::Printf(LEVEL_ERROR, "error: module %s: kernel is not a boolean\n", mod_name); 455 | json_decref(libs); 456 | return 0; 457 | } 458 | 459 | functions = json_object_get(mod_data, "functions"); 460 | if (!json_is_object(functions)) { 461 | COutput::Printf(LEVEL_ERROR, "error: module %s: functions is not an array\n", mod_name); 462 | json_decref(libs); 463 | return 0; 464 | } 465 | 466 | variables = json_object_get(mod_data, "variables"); 467 | if (variables == 0) { 468 | has_variables = 0; 469 | } 470 | 471 | if (has_variables && !json_is_object(variables)) { 472 | COutput::Printf(LEVEL_ERROR, "error: module %s: variables is not an array\n", mod_name); 473 | json_decref(libs); 474 | return 0; 475 | } 476 | 477 | LibraryEntry *pLib; 478 | 479 | COutput::Printf(LEVEL_DEBUG, "Library %s\n", mod_name); 480 | SAFE_ALLOC(pLib, LibraryEntry); 481 | if(pLib != NULL) 482 | { 483 | memset(pLib, 0, sizeof(LibraryEntry)); 484 | strcpy(pLib->lib_name, mod_name); 485 | strcpy(pLib->prx_name, mod_name); 486 | strcpy(pLib->prx, mod_name); 487 | if(strcmp(pLib->lib_name, MASTER_NID_MAPPER) == 0) 488 | { 489 | blMasterNids = true; 490 | COutput::Printf(LEVEL_DEBUG, "Found master NID table\n"); 491 | } 492 | 493 | int fCount = json_object_size(functions); 494 | int vCount = json_object_size(variables); 495 | 496 | pLib->vcount = vCount; 497 | pLib->fcount = fCount; 498 | if((fCount+vCount) > 0) 499 | { 500 | SAFE_ALLOC(pLib->pNids, LibraryNid[vCount+fCount]); 501 | if(pLib->pNids != NULL) 502 | { 503 | int iLoop = 0; 504 | const char *pName; 505 | 506 | memset(pLib->pNids, 0, sizeof(LibraryNid) * (vCount+fCount)); 507 | pLib->entry_count = vCount + fCount; 508 | 509 | k = -1; 510 | json_object_foreach(functions, target_name, target_nid) { 511 | k++; 512 | 513 | if (!json_is_integer(target_nid)) { 514 | COutput::Printf(LEVEL_ERROR, "error: function %s: nid is not an integer\n", target_name); 515 | json_decref(libs); 516 | return 0; 517 | } 518 | 519 | pLib->pNids[iLoop].pParentLib = pLib; 520 | pLib->pNids[iLoop].nid = json_integer_value(target_nid); 521 | strcpy(pLib->pNids[iLoop].name, target_name); 522 | COutput::Printf(LEVEL_DEBUG, "Read func:%s nid:0x%08X\n", pLib->pNids[iLoop].name, pLib->pNids[iLoop].nid); 523 | iLoop++; 524 | } 525 | 526 | if (has_variables) { 527 | k = -1; 528 | json_object_foreach(variables, target_name, target_nid) { 529 | k++; 530 | 531 | if (!json_is_integer(target_nid)) { 532 | COutput::Printf(LEVEL_ERROR, "error: variable %s: nid is not an integer\n", target_name); 533 | json_decref(libs); 534 | return 0; 535 | } 536 | 537 | pLib->pNids[iLoop].pParentLib = pLib; 538 | pLib->pNids[iLoop].nid = json_integer_value(target_nid); 539 | strcpy(pLib->pNids[iLoop].name, target_name); 540 | iLoop++; 541 | } 542 | } 543 | } 544 | } 545 | 546 | if(m_pLibHead == NULL) 547 | { 548 | m_pLibHead = pLib; 549 | } 550 | else 551 | { 552 | pLib->pNext = m_pLibHead; 553 | m_pLibHead = pLib; 554 | } 555 | 556 | if(blMasterNids) 557 | { 558 | m_pMasterNids = pLib; 559 | } 560 | } 561 | } 562 | } 563 | 564 | return 1; 565 | } 566 | 567 | bool CNidMgr::AddJsonFile(const char *szFilename) 568 | { 569 | FILE *fp = fopen(szFilename, "r"); 570 | if (fp == NULL) { 571 | COutput::Printf(LEVEL_ERROR, "Error: could not open %s\n", szFilename); 572 | return NULL; 573 | } 574 | 575 | vita_imports_loads(fp, 1); 576 | 577 | fclose(fp); 578 | } 579 | 580 | /* Find the name based on our list of names */ 581 | const char *CNidMgr::FindLibName(const char *lib, u32 nid) 582 | { 583 | return SearchLibs(lib, nid); 584 | } 585 | 586 | LibraryEntry *CNidMgr::GetLibraries(void) 587 | { 588 | return m_pLibHead; 589 | } 590 | 591 | /* Find the name of the dependany library for a specified lib */ 592 | const char *CNidMgr::FindDependancy(const char *lib) 593 | { 594 | LibraryEntry *pLib; 595 | 596 | pLib = m_pLibHead; 597 | 598 | while(pLib != NULL) 599 | { 600 | if(strcmp(pLib->lib_name, lib) == 0) 601 | { 602 | return pLib->prx; 603 | } 604 | 605 | pLib = pLib->pNext; 606 | } 607 | 608 | return NULL; 609 | } 610 | 611 | static char *strip_whitesp(char *str) 612 | { 613 | int len; 614 | 615 | while(isspace(*str)) 616 | { 617 | str++; 618 | } 619 | 620 | len = strlen(str); 621 | while((len > 0) && (isspace(str[len-1]))) 622 | { 623 | str[len-1] = 0; 624 | len--; 625 | } 626 | 627 | if(len == 0) 628 | { 629 | return NULL; 630 | } 631 | 632 | return str; 633 | } 634 | 635 | bool CNidMgr::AddFunctionFile(const char *szFilename) 636 | { 637 | FILE *fp; 638 | 639 | fp = fopen(szFilename, "r"); 640 | if(fp) 641 | { 642 | char line[1024]; 643 | 644 | while(fgets(line, sizeof(line), fp)) 645 | { 646 | char *name; 647 | char *args = NULL; 648 | char *ret = NULL; 649 | 650 | name = strip_whitesp(line); 651 | if(name == NULL) 652 | { 653 | continue; 654 | } 655 | 656 | args = strchr(name, '|'); 657 | if(args) 658 | { 659 | *args++ = 0; 660 | ret = strchr(args, '|'); 661 | if(ret) 662 | { 663 | *ret++ = 0; 664 | } 665 | } 666 | 667 | if((name) && (name[0] != '#')) 668 | { 669 | FunctionType *p = new FunctionType; 670 | 671 | memset(p, 0, sizeof(FunctionType)); 672 | snprintf(p->name, FUNCTION_NAME_MAX, "%s", name); 673 | if(args) 674 | { 675 | snprintf(p->args, FUNCTION_ARGS_MAX, "%s", args); 676 | } 677 | if(ret) 678 | { 679 | snprintf(p->ret, FUNCTION_RET_MAX, "%s", ret); 680 | } 681 | m_funcMap.insert(m_funcMap.end(), p); 682 | COutput::Printf(LEVEL_DEBUG, "Function: %s %s(%s)\n", p->ret, p->name, p->args); 683 | } 684 | } 685 | fclose(fp); 686 | return true; 687 | } 688 | 689 | return false; 690 | } 691 | 692 | FunctionType *CNidMgr::FindFunctionType(const char *name) 693 | { 694 | FunctionType *ret = NULL; 695 | 696 | for(unsigned int i = 0; i < m_funcMap.size(); i++) 697 | { 698 | FunctionType *p = NULL; 699 | p = m_funcMap[i]; 700 | if((p) && (strcmp(name, p->name) == 0)) 701 | { 702 | ret = p; 703 | break; 704 | } 705 | } 706 | 707 | return ret; 708 | } 709 | -------------------------------------------------------------------------------- /NidMgr.h: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | * PRXTool : Utility for PSP executables. 3 | * (c) TyRaNiD 2k5 4 | * 5 | * NidMgr.h - Definition of a class to manipulate a list 6 | * of NID Libraries. 7 | ***************************************************************/ 8 | 9 | #ifndef __NIDMGR_H__ 10 | #define __NIDMGR_H__ 11 | 12 | #include "types.h" 13 | #include 14 | #include 15 | 16 | #define LIB_NAME_MAX 64 17 | #define LIB_SYMBOL_NAME_MAX 128 18 | 19 | #define FUNCTION_NAME_MAX 128 20 | #define FUNCTION_ARGS_MAX 128 21 | #define FUNCTION_RET_MAX 64 22 | 23 | struct LibraryEntry; 24 | 25 | /** Structure to hold a single library nid */ 26 | struct LibraryNid 27 | { 28 | /** The NID value for this symbol */ 29 | u32 nid; 30 | /** The name of the symbol */ 31 | char name[LIB_SYMBOL_NAME_MAX]; 32 | /** The parent library */ 33 | struct LibraryEntry *pParentLib; 34 | }; 35 | 36 | /** Structure to hold a single function entry */ 37 | struct FunctionType 38 | { 39 | char name[FUNCTION_NAME_MAX]; 40 | char args[FUNCTION_ARGS_MAX]; 41 | char ret[FUNCTION_RET_MAX]; 42 | }; 43 | 44 | /** Structure to hold a single library entry */ 45 | struct LibraryEntry 46 | { 47 | /** Pointer to the next library in the chain */ 48 | struct LibraryEntry* pNext; 49 | /** The PRX name (i.e. module name) of the file containing this lib */ 50 | char prx_name[LIB_NAME_MAX]; 51 | /** The name of the library */ 52 | char lib_name[LIB_NAME_MAX]; 53 | /** The filename of the module containing this lib (for dependancies) */ 54 | char prx[MAXPATH]; 55 | /** The flags as defined in the export */ 56 | int flags; 57 | /** The number of entries in the NID list */ 58 | int entry_count; 59 | /** The number of variable NIDs in the list */ 60 | int vcount; 61 | /** The number of function NIDs in the list */ 62 | int fcount; 63 | /** A pointer to a list of NIDs */ 64 | LibraryNid *pNids; 65 | }; 66 | 67 | /** Class to load and manage a list of libraries */ 68 | class CNidMgr 69 | { 70 | typedef std::vector FunctionVect; 71 | 72 | /** Head pointer to the list of libraries */ 73 | LibraryEntry *m_pLibHead; 74 | /** Mapping of function names to prototypes */ 75 | FunctionVect m_funcMap; 76 | /** A buffer to store a pre-generated symbol name so it can be passed to the caller */ 77 | char m_szCurrName[LIB_SYMBOL_NAME_MAX]; 78 | /** Indicator that we have loaded a master NID file */ 79 | LibraryEntry *m_pMasterNids; 80 | /** Generate a name */ 81 | const char *GenName(const char *lib, u32 nid); 82 | /** Search the loaded libs for a symbol */ 83 | const char *SearchLibs(const char *lib, u32 nid); 84 | void FreeMemory(); 85 | const char* ReadNid(TiXmlElement *pElement, u32 &nid); 86 | int CountNids(TiXmlElement *pElement, const char *name); 87 | void ProcessLibrary(TiXmlElement *pLibrary, const char *prx_name, const char *prx); 88 | void ProcessPrxfile(TiXmlElement *pPrxfile); 89 | public: 90 | CNidMgr(); 91 | ~CNidMgr(); 92 | const char *FindLibName(const char *lib, u32 nid); 93 | const char *FindDependancy(const char *lib); 94 | bool AddXmlFile(const char *szFilename); 95 | bool AddJsonFile(const char *szFilename); 96 | int vita_imports_loads(FILE *text, int verbose); 97 | LibraryEntry *GetLibraries(void); 98 | bool AddFunctionFile(const char *szFilename); 99 | FunctionType *FindFunctionType(const char *name); 100 | }; 101 | 102 | #endif 103 | -------------------------------------------------------------------------------- /ProcessElf.C: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | * PRXTool : Utility for PSP executables. 3 | * (c) TyRaNiD 2k5 4 | * 5 | * ProcessElf.C - Implementation of a class to manipulate a ELF 6 | ***************************************************************/ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "ProcessElf.h" 13 | #include "output.h" 14 | 15 | CProcessElf::CProcessElf() 16 | : m_pElf(NULL) 17 | , m_iElfSize(0) 18 | , m_pElfBin(NULL) 19 | , m_iBinSize(0) 20 | , m_blElfLoaded(false) 21 | , m_pElfSections(NULL) 22 | , m_iSHCount(0) 23 | , m_pElfPrograms(NULL) 24 | , m_iPHCount(0) 25 | , m_pElfStrtab(NULL) 26 | , m_pElfSymbols(NULL) 27 | , m_iSymCount(0) 28 | , m_iBaseAddr(0) 29 | { 30 | memset(&m_elfHeader, 0, sizeof(m_elfHeader)); 31 | } 32 | 33 | CProcessElf::~CProcessElf() 34 | { 35 | FreeMemory(); 36 | } 37 | 38 | void CProcessElf::FreeMemory() 39 | { 40 | if(m_pElfSections != NULL) 41 | { 42 | delete m_pElfSections; 43 | m_pElfSections = NULL; 44 | } 45 | 46 | if(m_pElfPrograms != NULL) 47 | { 48 | delete m_pElfPrograms; 49 | m_pElfPrograms = NULL; 50 | } 51 | 52 | if(m_pElfSymbols != NULL) 53 | { 54 | delete m_pElfSymbols; 55 | m_pElfSymbols = NULL; 56 | } 57 | 58 | /* Just an aliased pointer */ 59 | m_pElfStrtab = NULL; 60 | 61 | if(m_pElf != NULL) 62 | { 63 | delete m_pElf; 64 | m_pElf = NULL; 65 | } 66 | m_iElfSize = 0; 67 | 68 | if(m_pElfBin != NULL) 69 | { 70 | delete m_pElfBin; 71 | m_pElfBin = NULL; 72 | } 73 | m_iBinSize = 0; 74 | 75 | m_blElfLoaded = false; 76 | } 77 | 78 | u8* CProcessElf::LoadFileToMem(const char *szFilename, u32 &lSize) 79 | { 80 | FILE *fp; 81 | u8 *pData; 82 | 83 | pData = NULL; 84 | 85 | fp = fopen(szFilename, "rb"); 86 | if(fp != NULL) 87 | { 88 | (void) fseek(fp, 0, SEEK_END); 89 | lSize = ftell(fp); 90 | rewind(fp); 91 | 92 | if(lSize >= sizeof(Elf32_Ehdr)) 93 | { 94 | SAFE_ALLOC(pData, u8[lSize]); 95 | if(pData != NULL) 96 | { 97 | if(fread(pData, 1, lSize, fp) != lSize) 98 | { 99 | COutput::Puts(LEVEL_ERROR, "Could not read in file data"); 100 | delete pData; 101 | pData = NULL; 102 | } 103 | } 104 | else 105 | { 106 | COutput::Puts(LEVEL_ERROR, "Could not allocate memory"); 107 | } 108 | } 109 | else 110 | { 111 | COutput::Puts(LEVEL_ERROR, "File not large enough to contain an ELF"); 112 | } 113 | 114 | fclose(fp); 115 | fp = NULL; 116 | } 117 | else 118 | { 119 | COutput::Printf(LEVEL_ERROR, "Could not open file %s\n", szFilename); 120 | } 121 | 122 | return pData; 123 | } 124 | 125 | void CProcessElf::ElfDumpHeader() 126 | { 127 | COutput::Puts(LEVEL_DEBUG, "ELF Header:"); 128 | COutput::Printf(LEVEL_DEBUG, "Magic %08X\n", m_elfHeader.iMagic); 129 | COutput::Printf(LEVEL_DEBUG, "Class %d\n", m_elfHeader.iClass); 130 | COutput::Printf(LEVEL_DEBUG, "Data %d\n", m_elfHeader.iData); 131 | COutput::Printf(LEVEL_DEBUG, "Idver %d\n", m_elfHeader.iIdver); 132 | COutput::Printf(LEVEL_DEBUG, "Type %04X\n", m_elfHeader.iType); 133 | COutput::Printf(LEVEL_DEBUG, "Start %08X\n", m_elfHeader.iEntry); 134 | COutput::Printf(LEVEL_DEBUG, "PH Offs %08X\n", m_elfHeader.iPhoff); 135 | COutput::Printf(LEVEL_DEBUG, "SH Offs %08X\n", m_elfHeader.iShoff); 136 | COutput::Printf(LEVEL_DEBUG, "Flags %08X\n", m_elfHeader.iFlags); 137 | COutput::Printf(LEVEL_DEBUG, "EH Size %d\n", m_elfHeader.iEhsize); 138 | COutput::Printf(LEVEL_DEBUG, "PHEntSize %d\n", m_elfHeader.iPhentsize); 139 | COutput::Printf(LEVEL_DEBUG, "PHNum %d\n", m_elfHeader.iPhnum); 140 | COutput::Printf(LEVEL_DEBUG, "SHEntSize %d\n", m_elfHeader.iShentsize); 141 | COutput::Printf(LEVEL_DEBUG, "SHNum %d\n", m_elfHeader.iShnum); 142 | COutput::Printf(LEVEL_DEBUG, "SHStrndx %d\n\n", m_elfHeader.iShstrndx); 143 | } 144 | 145 | void CProcessElf::ElfLoadHeader(const Elf32_Ehdr* pHeader) 146 | { 147 | m_elfHeader.iMagic = LW(pHeader->e_magic); 148 | m_elfHeader.iClass = pHeader->e_class; 149 | m_elfHeader.iData = pHeader->e_data; 150 | m_elfHeader.iIdver = pHeader->e_idver; 151 | m_elfHeader.iType = LH(pHeader->e_type); 152 | m_elfHeader.iMachine = LH(pHeader->e_machine); 153 | m_elfHeader.iVersion = LW(pHeader->e_version); 154 | m_elfHeader.iEntry = LW(pHeader->e_entry); 155 | m_elfHeader.iPhoff = LW(pHeader->e_phoff); 156 | m_elfHeader.iShoff = LW(pHeader->e_shoff); 157 | m_elfHeader.iFlags = LW(pHeader->e_flags); 158 | m_elfHeader.iEhsize = LH(pHeader->e_ehsize); 159 | m_elfHeader.iPhentsize = LH(pHeader->e_phentsize); 160 | m_elfHeader.iPhnum = LH(pHeader->e_phnum); 161 | m_elfHeader.iShentsize = LH(pHeader->e_shentsize); 162 | m_elfHeader.iShnum = LH(pHeader->e_shnum); 163 | m_elfHeader.iShstrndx = LH(pHeader->e_shstrndx); 164 | } 165 | 166 | bool CProcessElf::ElfValidateHeader() 167 | { 168 | Elf32_Ehdr* pHeader; 169 | bool blRet = false; 170 | 171 | assert(m_pElf != NULL); 172 | assert(m_iElfSize > 0); 173 | 174 | pHeader = (Elf32_Ehdr*) m_pElf; 175 | 176 | ElfLoadHeader(pHeader); 177 | 178 | if(m_elfHeader.iMagic == ELF_MAGIC) 179 | { 180 | u32 iPhend = 0; 181 | u32 iShend = 0; 182 | 183 | /* Check that if we have program and section headers they are valid */ 184 | if(m_elfHeader.iPhnum > 0) 185 | { 186 | iPhend = m_elfHeader.iPhoff + (m_elfHeader.iPhentsize * m_elfHeader.iPhnum); 187 | } 188 | 189 | if(m_elfHeader.iShnum > 0) 190 | { 191 | iShend = m_elfHeader.iShoff + (m_elfHeader.iShentsize * m_elfHeader.iShnum); 192 | } 193 | 194 | COutput::Printf(LEVEL_DEBUG, "%08X, %08X, %08X\n", iPhend, iShend, m_iElfSize); 195 | 196 | if((iPhend <= m_iElfSize) && (iShend <= m_iElfSize)) 197 | { 198 | blRet = true; 199 | } 200 | else 201 | { 202 | COutput::Puts(LEVEL_ERROR, "Program or sections header information invalid"); 203 | } 204 | } 205 | else 206 | { 207 | COutput::Puts(LEVEL_ERROR, "Magic value incorrect (not an ELF?)"); 208 | } 209 | 210 | if(COutput::GetDebug()) 211 | { 212 | ElfDumpHeader(); 213 | } 214 | 215 | return blRet; 216 | } 217 | 218 | ElfSection* CProcessElf::ElfFindSection(const char *szName) 219 | { 220 | ElfSection* pSection = NULL; 221 | 222 | if((m_pElfSections != NULL) && (m_iSHCount > 0) && (m_pElfStrtab != NULL)) 223 | { 224 | int iLoop; 225 | 226 | if(szName == NULL) 227 | { 228 | /* Return the default entry, kinda pointless :P */ 229 | pSection = &m_pElfSections[0]; 230 | } 231 | else 232 | { 233 | for(iLoop = 0; iLoop < m_iSHCount; iLoop++) 234 | { 235 | if(strcmp(m_pElfSections[iLoop].szName, szName) == 0) 236 | { 237 | pSection = &m_pElfSections[iLoop]; 238 | } 239 | } 240 | } 241 | } 242 | 243 | return pSection; 244 | } 245 | 246 | ElfSection *CProcessElf::ElfFindSectionByAddr(unsigned int dwAddr) 247 | { 248 | ElfSection* pSection = NULL; 249 | 250 | if((m_pElfSections != NULL) && (m_iSHCount > 0) && (m_pElfStrtab != NULL)) 251 | { 252 | int iLoop; 253 | 254 | for(iLoop = 0; iLoop < m_iSHCount; iLoop++) 255 | { 256 | if(m_pElfSections[iLoop].iFlags & SHF_ALLOC) 257 | { 258 | u32 sectaddr = m_pElfSections[iLoop].iAddr; 259 | u32 sectsize = m_pElfSections[iLoop].iSize; 260 | 261 | if((dwAddr >= sectaddr) && (dwAddr < (sectaddr + sectsize))) 262 | { 263 | pSection = &m_pElfSections[iLoop]; 264 | } 265 | } 266 | } 267 | } 268 | 269 | return pSection; 270 | } 271 | 272 | bool CProcessElf::ElfAddrIsText(unsigned int dwAddr) 273 | { 274 | bool blRet = false; 275 | ElfSection *sect; 276 | 277 | sect = ElfFindSectionByAddr(dwAddr); 278 | if(sect) 279 | { 280 | if(sect->iFlags & SHF_EXECINSTR) 281 | { 282 | blRet = true; 283 | } 284 | } 285 | 286 | return blRet; 287 | } 288 | 289 | const char *CProcessElf::GetSymbolName(u32 name, u32 shndx) 290 | { 291 | if((shndx > 0) && (shndx < (u32) m_iSHCount)) 292 | { 293 | if((m_pElfSections[shndx].iType == SHT_STRTAB) && (name < m_pElfSections[shndx].iSize)) 294 | { 295 | return (char *) (m_pElfSections[shndx].pData + name); 296 | } 297 | } 298 | 299 | return ""; 300 | } 301 | 302 | bool CProcessElf::LoadPrograms() 303 | { 304 | bool blRet = true; 305 | 306 | if((m_elfHeader.iPhoff > 0) && (m_elfHeader.iPhnum > 0) && (m_elfHeader.iPhentsize > 0)) 307 | { 308 | Elf32_Phdr *pHeader; 309 | u8 *pData; 310 | u32 iLoop; 311 | 312 | pData = m_pElf + m_elfHeader.iPhoff; 313 | 314 | SAFE_ALLOC(m_pElfPrograms, ElfProgram[m_elfHeader.iPhnum]); 315 | 316 | if(m_pElfPrograms != NULL) 317 | { 318 | m_iPHCount = m_elfHeader.iPhnum; 319 | COutput::Puts(LEVEL_DEBUG, "Program Headers:"); 320 | 321 | for(iLoop = 0; iLoop < (u32) m_iPHCount; iLoop++) 322 | { 323 | pHeader = (Elf32_Phdr *) pData; 324 | m_pElfPrograms[iLoop].iType = LW(pHeader->p_type); 325 | m_pElfPrograms[iLoop].iOffset = LW(pHeader->p_offset); 326 | m_pElfPrograms[iLoop].iVaddr = LW(pHeader->p_vaddr); 327 | m_pElfPrograms[iLoop].iPaddr = LW(pHeader->p_paddr); 328 | m_pElfPrograms[iLoop].iFilesz = LW(pHeader->p_filesz); 329 | m_pElfPrograms[iLoop].iMemsz = LW(pHeader->p_memsz); 330 | m_pElfPrograms[iLoop].iFlags = LW(pHeader->p_flags); 331 | m_pElfPrograms[iLoop].iAlign = LW(pHeader->p_align); 332 | m_pElfPrograms[iLoop].pData = m_pElf + m_pElfPrograms[iLoop].iOffset; 333 | 334 | pData += m_elfHeader.iPhentsize; 335 | } 336 | 337 | if(COutput::GetDebug()) 338 | { 339 | for(iLoop = 0; iLoop < (u32) m_iPHCount; iLoop++) 340 | { 341 | COutput::Printf(LEVEL_DEBUG, "Program Header %d:\n", iLoop); 342 | COutput::Printf(LEVEL_DEBUG, "Type: %08X\n", m_pElfPrograms[iLoop].iType); 343 | COutput::Printf(LEVEL_DEBUG, "Offset: %08X\n", m_pElfPrograms[iLoop].iOffset); 344 | COutput::Printf(LEVEL_DEBUG, "VAddr: %08X\n", m_pElfPrograms[iLoop].iVaddr); 345 | COutput::Printf(LEVEL_DEBUG, "PAddr: %08X\n", m_pElfPrograms[iLoop].iPaddr); 346 | COutput::Printf(LEVEL_DEBUG, "FileSz: %d\n", m_pElfPrograms[iLoop].iFilesz); 347 | COutput::Printf(LEVEL_DEBUG, "MemSz: %d\n", m_pElfPrograms[iLoop].iMemsz); 348 | COutput::Printf(LEVEL_DEBUG, "Flags: %08X\n", m_pElfPrograms[iLoop].iFlags); 349 | COutput::Printf(LEVEL_DEBUG, "Align: %08X\n\n", m_pElfPrograms[iLoop].iAlign); 350 | } 351 | } 352 | } 353 | else 354 | { 355 | blRet = false; 356 | } 357 | } 358 | 359 | return blRet; 360 | } 361 | 362 | bool CProcessElf::LoadSymbols() 363 | { 364 | ElfSection *pSymtab; 365 | bool blRet = true; 366 | 367 | COutput::Printf(LEVEL_DEBUG, "Size %d\n", sizeof(Elf32_Sym)); 368 | 369 | pSymtab = ElfFindSection(".symtab"); 370 | if((pSymtab != NULL) && (pSymtab->iType == SHT_SYMTAB) && (pSymtab->pData != NULL)) 371 | { 372 | Elf32_Sym *pSym; 373 | int iLoop, iSymcount; 374 | u32 symidx; 375 | 376 | symidx = pSymtab->iLink; 377 | iSymcount = pSymtab->iSize / sizeof(Elf32_Sym); 378 | SAFE_ALLOC(m_pElfSymbols, ElfSymbol[iSymcount]); 379 | if(m_pElfSymbols != NULL) 380 | { 381 | m_iSymCount = iSymcount; 382 | pSym = (Elf32_Sym*) pSymtab->pData; 383 | for(iLoop = 0; iLoop < iSymcount; iLoop++) 384 | { 385 | m_pElfSymbols[iLoop].name = LW(pSym->st_name); 386 | m_pElfSymbols[iLoop].symname = GetSymbolName(m_pElfSymbols[iLoop].name, symidx); 387 | m_pElfSymbols[iLoop].value = LW(pSym->st_value); 388 | m_pElfSymbols[iLoop].size = LW(pSym->st_size); 389 | m_pElfSymbols[iLoop].info = pSym->st_info; 390 | m_pElfSymbols[iLoop].other = pSym->st_other; 391 | m_pElfSymbols[iLoop].shndx = LH(pSym->st_shndx); 392 | COutput::Printf(LEVEL_DEBUG, "Symbol %d\n", iLoop); 393 | COutput::Printf(LEVEL_DEBUG, "Name %d, '%s'\n", m_pElfSymbols[iLoop].name, m_pElfSymbols[iLoop].symname); 394 | COutput::Printf(LEVEL_DEBUG, "Value %08X\n",m_pElfSymbols[iLoop].value); 395 | COutput::Printf(LEVEL_DEBUG, "Size %08X\n", m_pElfSymbols[iLoop].size); 396 | COutput::Printf(LEVEL_DEBUG, "Info %02X\n", m_pElfSymbols[iLoop].info); 397 | COutput::Printf(LEVEL_DEBUG, "Other %02X\n", m_pElfSymbols[iLoop].other); 398 | COutput::Printf(LEVEL_DEBUG, "Shndx %04X\n\n", m_pElfSymbols[iLoop].shndx); 399 | pSym++; 400 | } 401 | } 402 | else 403 | { 404 | COutput::Printf(LEVEL_ERROR, "Could not allocate memory for symbols\n"); 405 | blRet = false; 406 | } 407 | } 408 | 409 | return blRet; 410 | } 411 | 412 | bool CProcessElf::FillSection(ElfSection& elfSect, const Elf32_Shdr *pSection) 413 | { 414 | assert(pSection != NULL); 415 | 416 | elfSect.iName = LW(pSection->sh_name); 417 | elfSect.iType = LW(pSection->sh_type); 418 | elfSect.iFlags = LW(pSection->sh_flags); 419 | elfSect.iAddr = LW(pSection->sh_addr); 420 | elfSect.iOffset = LW(pSection->sh_offset); 421 | elfSect.iSize = LW(pSection->sh_size); 422 | elfSect.iLink = LW(pSection->sh_link); 423 | elfSect.iInfo = LW(pSection->sh_info); 424 | elfSect.iAddralign = LW(pSection->sh_addralign); 425 | elfSect.iEntsize = LW(pSection->sh_entsize); 426 | elfSect.pData = m_pElf + elfSect.iOffset; 427 | elfSect.pRelocs = NULL; 428 | elfSect.iRelocCount = 0; 429 | 430 | if(((elfSect.pData + elfSect.iSize) > (m_pElf + m_iElfSize)) && (elfSect.iType != SHT_NOBITS)) 431 | { 432 | COutput::Puts(LEVEL_ERROR, "Section too big for file"); 433 | elfSect.pData = NULL; 434 | return false; 435 | } 436 | 437 | return true; 438 | } 439 | 440 | void CProcessElf::ElfDumpSections() 441 | { 442 | int iLoop; 443 | assert(m_pElfSections != NULL); 444 | 445 | for(iLoop = 0; iLoop < m_iSHCount; iLoop++) 446 | { 447 | ElfSection* pSection; 448 | 449 | pSection = &m_pElfSections[iLoop]; 450 | COutput::Printf(LEVEL_DEBUG, "Section %d\n", iLoop); 451 | COutput::Printf(LEVEL_DEBUG, "Name: %d %s\n", pSection->iName, pSection->szName); 452 | COutput::Printf(LEVEL_DEBUG, "Type: %08X\n", pSection->iType); 453 | COutput::Printf(LEVEL_DEBUG, "Flags: %08X\n", pSection->iFlags); 454 | COutput::Printf(LEVEL_DEBUG, "Addr: %08X\n", pSection->iAddr); 455 | COutput::Printf(LEVEL_DEBUG, "Offset: %08X\n", pSection->iOffset); 456 | COutput::Printf(LEVEL_DEBUG, "Size: %08X\n", pSection->iSize); 457 | COutput::Printf(LEVEL_DEBUG, "Link: %08X\n", pSection->iLink); 458 | COutput::Printf(LEVEL_DEBUG, "Info: %08X\n", pSection->iInfo); 459 | COutput::Printf(LEVEL_DEBUG, "Addralign: %08X\n", pSection->iAddralign); 460 | COutput::Printf(LEVEL_DEBUG, "Entsize: %08X\n", pSection->iEntsize); 461 | COutput::Printf(LEVEL_DEBUG, "Data %p\n\n", pSection->pData); 462 | } 463 | } 464 | 465 | /* Build a binary image of the elf file in memory */ 466 | /* Really should build the binary image from program headers if no section headers */ 467 | bool CProcessElf::BuildBinaryImage() 468 | { 469 | bool blRet = false; 470 | int iLoop; 471 | u32 iMinAddr = 0xFFFFFFFF; 472 | u32 iMaxAddr = 0; 473 | long iMaxSize = 0; 474 | 475 | assert(m_pElf != NULL); 476 | assert(m_iElfSize > 0); 477 | assert(m_pElfBin == NULL); 478 | assert(m_iBinSize == 0); 479 | 480 | /* Find the maximum and minimum addresses */ 481 | if(m_elfHeader.iType == ELF_MIPS_TYPE) 482 | { 483 | COutput::Printf(LEVEL_DEBUG, "Using Section Headers for binary image\n"); 484 | /* If ELF type then use the sections */ 485 | for(iLoop = 0; iLoop < m_iSHCount; iLoop++) 486 | { 487 | ElfSection* pSection; 488 | 489 | pSection = &m_pElfSections[iLoop]; 490 | 491 | if(pSection->iFlags & SHF_ALLOC) 492 | { 493 | if((pSection->iAddr + pSection->iSize) > (iMaxAddr + iMaxSize)) 494 | { 495 | iMaxAddr = pSection->iAddr; 496 | iMaxSize = pSection->iSize; 497 | } 498 | 499 | if(pSection->iAddr < iMinAddr) 500 | { 501 | iMinAddr = pSection->iAddr; 502 | } 503 | } 504 | } 505 | 506 | COutput::Printf(LEVEL_DEBUG, "Min Address %08X, Max Address %08X, Max Size %d\n", 507 | iMinAddr, iMaxAddr, iMaxSize); 508 | 509 | if(iMinAddr != 0xFFFFFFFF) 510 | { 511 | m_iBinSize = iMaxAddr - iMinAddr + iMaxSize; 512 | SAFE_ALLOC(m_pElfBin, u8[m_iBinSize]); 513 | if(m_pElfBin != NULL) 514 | { 515 | memset(m_pElfBin, 0, m_iBinSize); 516 | for(iLoop = 0; iLoop < m_iSHCount; iLoop++) 517 | { 518 | ElfSection* pSection = &m_pElfSections[iLoop]; 519 | 520 | if((pSection->iFlags & SHF_ALLOC) && (pSection->iType != SHT_NOBITS) && (pSection->pData != NULL)) 521 | { 522 | memcpy(m_pElfBin + (pSection->iAddr - iMinAddr), pSection->pData, pSection->iSize); 523 | } 524 | } 525 | 526 | m_iBaseAddr = iMinAddr; 527 | blRet = true; 528 | } 529 | } 530 | } 531 | else 532 | { 533 | /* If PRX use the program headers */ 534 | COutput::Printf(LEVEL_DEBUG, "Using Program Headers for binary image\n"); 535 | for(iLoop = 0; iLoop < m_iPHCount; iLoop++) 536 | { 537 | ElfProgram* pProgram; 538 | 539 | pProgram = &m_pElfPrograms[iLoop]; 540 | 541 | if(pProgram->iType == PT_LOAD) 542 | { 543 | if((pProgram->iVaddr + pProgram->iMemsz) > iMaxAddr) 544 | { 545 | iMaxAddr = pProgram->iVaddr + pProgram->iMemsz; 546 | } 547 | 548 | if(pProgram->iVaddr < iMinAddr) 549 | { 550 | iMinAddr = pProgram->iVaddr; 551 | } 552 | } 553 | } 554 | 555 | COutput::Printf(LEVEL_DEBUG, "Min Address %08X, Max Address %08X\n", 556 | iMinAddr, iMaxAddr); 557 | 558 | if(iMinAddr != 0xFFFFFFFF) 559 | { 560 | m_iBinSize = iMaxAddr - iMinAddr; 561 | SAFE_ALLOC(m_pElfBin, u8[m_iBinSize]); 562 | if(m_pElfBin != NULL) 563 | { 564 | memset(m_pElfBin, 0, m_iBinSize); 565 | for(iLoop = 0; iLoop < m_iPHCount; iLoop++) 566 | { 567 | ElfProgram* pProgram = &m_pElfPrograms[iLoop]; 568 | 569 | if((pProgram->iType == PT_LOAD) && (pProgram->pData != NULL)) 570 | { 571 | COutput::Printf(LEVEL_DEBUG, "Loading program %d 0x%08X\n", iLoop, pProgram->iType); 572 | memcpy(m_pElfBin + (pProgram->iVaddr - iMinAddr), pProgram->pData, pProgram->iFilesz); 573 | } 574 | } 575 | 576 | m_iBaseAddr = iMinAddr; 577 | blRet = true; 578 | } 579 | } 580 | } 581 | 582 | return blRet; 583 | } 584 | 585 | bool CProcessElf::LoadSections() 586 | { 587 | bool blRet = true; 588 | 589 | assert(m_pElf != NULL); 590 | 591 | if((m_elfHeader.iShoff != 0) && (m_elfHeader.iShnum > 0) && (m_elfHeader.iShentsize > 0)) 592 | { 593 | SAFE_ALLOC(m_pElfSections, ElfSection[m_elfHeader.iShnum]); 594 | if(m_pElfSections != NULL) 595 | { 596 | int iLoop; 597 | u8 *pData; 598 | Elf32_Shdr *pSection; 599 | 600 | m_iSHCount = m_elfHeader.iShnum; 601 | memset(m_pElfSections, 0, sizeof(ElfSection) * m_iSHCount); 602 | pData = m_pElf + m_elfHeader.iShoff; 603 | 604 | for(iLoop = 0; iLoop < m_iSHCount; iLoop++) 605 | { 606 | pSection = (Elf32_Shdr*) pData; 607 | if(FillSection(m_pElfSections[iLoop], pSection) == false) 608 | { 609 | blRet = false; 610 | break; 611 | } 612 | 613 | pData += m_elfHeader.iShentsize; 614 | } 615 | 616 | if((m_elfHeader.iShstrndx > 0) && (m_elfHeader.iShstrndx < (u32) m_iSHCount)) 617 | { 618 | if(m_pElfSections[m_elfHeader.iShstrndx].iType == SHT_STRTAB) 619 | { 620 | m_pElfStrtab = &m_pElfSections[m_elfHeader.iShstrndx]; 621 | } 622 | } 623 | 624 | if(blRet) 625 | { 626 | /* If we found a string table let's run through the sections fixing up names */ 627 | if(m_pElfStrtab != NULL) 628 | { 629 | for(iLoop = 0; iLoop < m_iSHCount; iLoop++) 630 | { 631 | strncpy(m_pElfSections[iLoop].szName, 632 | (char *) (m_pElfStrtab->pData + m_pElfSections[iLoop].iName), ELF_SECT_MAX_NAME - 1); 633 | m_pElfSections[iLoop].szName[ELF_SECT_MAX_NAME-1] = 0; 634 | } 635 | } 636 | 637 | if(COutput::GetDebug()) 638 | { 639 | ElfDumpSections(); 640 | } 641 | } 642 | } 643 | else 644 | { 645 | COutput::Puts(LEVEL_ERROR, "Could not allocate memory for sections"); 646 | blRet = false; 647 | } 648 | } 649 | return blRet; 650 | } 651 | 652 | u32 CProcessElf::ElfGetBaseAddr() 653 | { 654 | if(m_blElfLoaded) 655 | { 656 | return m_iBaseAddr; 657 | } 658 | 659 | return 0; 660 | } 661 | 662 | u32 CProcessElf::ElfGetTopAddr() 663 | { 664 | if(m_blElfLoaded) 665 | { 666 | return m_iBaseAddr + m_iBinSize; 667 | } 668 | 669 | return 0; 670 | } 671 | 672 | u32 CProcessElf::ElfGetLoadSize() 673 | { 674 | if(m_blElfLoaded) 675 | { 676 | return m_iBinSize; 677 | } 678 | 679 | return 0; 680 | } 681 | 682 | bool CProcessElf::LoadFromFile(const char *szFilename) 683 | { 684 | bool blRet = false; 685 | 686 | /* Return the object to a know state */ 687 | FreeMemory(); 688 | 689 | m_pElf = LoadFileToMem(szFilename, m_iElfSize); 690 | if((m_pElf != NULL) && (ElfValidateHeader() == true)) 691 | { 692 | if((LoadPrograms() == true) && (LoadSections() == true) && (LoadSymbols() == true) && (BuildBinaryImage() == true)) 693 | { 694 | strncpy(m_szFilename, szFilename, MAXPATH-1); 695 | m_szFilename[MAXPATH-1] = 0; 696 | blRet = true; 697 | m_blElfLoaded = true; 698 | } 699 | } 700 | 701 | if(blRet == false) 702 | { 703 | FreeMemory(); 704 | } 705 | 706 | return blRet; 707 | } 708 | 709 | bool CProcessElf::BuildFakeSections(unsigned int dwDataBase) 710 | { 711 | bool blRet = false; 712 | 713 | if(dwDataBase >= m_iBinSize) 714 | { 715 | /* If invalid then set to 0 */ 716 | COutput::Printf(LEVEL_INFO, "Invalid data base address (%d), defaulting to 0\n", dwDataBase); 717 | dwDataBase = 0; 718 | } 719 | 720 | SAFE_ALLOC(m_pElfSections, ElfSection[3]); 721 | if(m_pElfSections) 722 | { 723 | unsigned int textsize = m_iBinSize; 724 | unsigned int datasize = m_iBinSize; 725 | 726 | if(dwDataBase > 0) 727 | { 728 | textsize = dwDataBase; 729 | datasize = m_iBinSize - dwDataBase; 730 | } 731 | 732 | m_iSHCount = 3; 733 | memset(m_pElfSections, 0, sizeof(ElfSection) * 3); 734 | m_pElfSections[1].iType = SHT_PROGBITS; 735 | m_pElfSections[1].iFlags = SHF_ALLOC | SHF_EXECINSTR; 736 | m_pElfSections[1].pData = m_pElfBin; 737 | m_pElfSections[1].iSize = textsize; 738 | strcpy(m_pElfSections[1].szName, ".text"); 739 | m_pElfSections[2].iType = SHT_PROGBITS; 740 | m_pElfSections[2].iFlags = SHF_ALLOC; 741 | m_pElfSections[2].iAddr = dwDataBase; 742 | m_pElfSections[2].pData = m_pElfBin + dwDataBase; 743 | m_pElfSections[2].iSize = datasize; 744 | strcpy(m_pElfSections[2].szName, ".data"); 745 | blRet = true; 746 | } 747 | 748 | return blRet; 749 | } 750 | 751 | bool CProcessElf::LoadFromBinFile(const char *szFilename, unsigned int dwDataBase) 752 | { 753 | bool blRet = false; 754 | 755 | /* Return the object to a know state */ 756 | FreeMemory(); 757 | 758 | m_pElfBin = LoadFileToMem(szFilename, m_iBinSize); 759 | if((m_pElfBin != NULL) && (BuildFakeSections(dwDataBase))) 760 | { 761 | strncpy(m_szFilename, szFilename, MAXPATH-1); 762 | m_szFilename[MAXPATH-1] = 0; 763 | blRet = true; 764 | m_blElfLoaded = true; 765 | } 766 | 767 | if(blRet == false) 768 | { 769 | FreeMemory(); 770 | } 771 | 772 | return blRet; 773 | } 774 | 775 | ElfSection* CProcessElf::ElfGetSections(u32 &iSHCount) 776 | { 777 | if(m_blElfLoaded) 778 | { 779 | iSHCount = m_iSHCount; 780 | return m_pElfSections; 781 | } 782 | 783 | return NULL; 784 | } 785 | 786 | const char *CProcessElf::GetElfName() 787 | { 788 | return m_szFilename; 789 | } 790 | -------------------------------------------------------------------------------- /ProcessElf.h: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | * PRXTool : Utility for PSP executables. 3 | * (c) TyRaNiD 2k5 4 | * 5 | * ProcessElf.h - Definition of a class to process ELF files. 6 | ***************************************************************/ 7 | 8 | #ifndef __PROCESS_ELF__ 9 | #define __PROCESS_ELF__ 10 | 11 | #include "types.h" 12 | #include "elftypes.h" 13 | 14 | class CProcessElf 15 | { 16 | protected: 17 | /* Pointers to the original elf and a binary image of the elf */ 18 | u8 *m_pElf; 19 | u32 m_iElfSize; 20 | u8 *m_pElfBin; 21 | u32 m_iBinSize; 22 | bool m_blElfLoaded; 23 | 24 | char m_szFilename[MAXPATH]; 25 | 26 | /* List of sections */ 27 | ElfSection *m_pElfSections; 28 | /* Number of elf section headers */ 29 | int m_iSHCount; 30 | /* Pointer to the program headers */ 31 | ElfProgram *m_pElfPrograms; 32 | /* Number of elf program headers */ 33 | int m_iPHCount; 34 | /* Pointer to the string table section */ 35 | ElfSection *m_pElfStrtab; 36 | /* Holds the elf header information */ 37 | ElfHeader m_elfHeader; 38 | /* List of symbols */ 39 | ElfSymbol *m_pElfSymbols; 40 | /* Number of symbols */ 41 | int m_iSymCount; 42 | 43 | /* The base address of the ELF */ 44 | u32 m_iBaseAddr; 45 | 46 | const char *GetSymbolName(u32 name, u32 shndx); 47 | 48 | void ElfLoadHeader(const Elf32_Ehdr* pHeader); 49 | bool ElfValidateHeader(); 50 | void ElfDumpHeader(); 51 | bool BuildBinaryImage(); 52 | bool BuildFakeSections(unsigned int dwDataBase); 53 | u8* LoadFileToMem(const char *szFilename, u32 &lSize); 54 | bool LoadPrograms(); 55 | bool FillSection(ElfSection& elfSect, const Elf32_Shdr *pSection); 56 | void ElfDumpSections(); 57 | bool LoadSections(); 58 | bool LoadSymbols(); 59 | void FreeMemory(); 60 | public: 61 | /** Default constructor */ 62 | CProcessElf(); 63 | /** Virtual destructor */ 64 | virtual ~CProcessElf(); 65 | /** Load an ELF from a file */ 66 | virtual bool LoadFromFile(const char *szFilename); 67 | /** Load a binary file */ 68 | virtual bool LoadFromBinFile(const char *szFilename, unsigned int dwDataBase); 69 | /** Find an elf section based on its name */ 70 | ElfSection *ElfFindSection(const char* szName); 71 | /** Find an elf section based on its address */ 72 | ElfSection *ElfFindSectionByAddr(unsigned int dwAddr); 73 | /** Determine if a section is a data section */ 74 | bool ElfAddrIsText(unsigned int dwAddr); 75 | /** Get the base address of the ELF */ 76 | u32 ElfGetBaseAddr(); 77 | /** Get the top address of the ELF */ 78 | u32 ElfGetTopAddr(); 79 | /** Get the size of the loaded ELF (as would be loaded in memory) */ 80 | u32 ElfGetLoadSize(); 81 | /** Get the section headers */ 82 | ElfSection* ElfGetSections(u32 &iSHCount); 83 | /** Get the file name of the loaded elf */ 84 | const char* GetElfName(); 85 | }; 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /ProcessPrx.h: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | * PRXTool : Utility for PSP executables. 3 | * (c) TyRaNiD 2k5 4 | * 5 | * ProcessPrx.h - Definition of a class to process PRX files. 6 | ***************************************************************/ 7 | 8 | #ifndef __PROCESSPRX_H__ 9 | #define __PROCESSPRX_H__ 10 | 11 | #include "ProcessElf.h" 12 | #include "VirtualMem.h" 13 | #include "prxtypes.h" 14 | #include "NidMgr.h" 15 | #include "disasm.h" 16 | 17 | /* Define ProcessPrx derived from ProcessElf */ 18 | class CProcessPrx : public CProcessElf 19 | { 20 | PspModule m_modInfo; 21 | CNidMgr m_defNidMgr; 22 | CNidMgr* m_pCurrNidMgr; 23 | CVirtualMem m_vMem; 24 | bool m_blPrxLoaded; 25 | /* Pointer to the allocated relocation entries, if available */ 26 | ElfReloc *m_pElfRelocs; 27 | /* Number of relocations */ 28 | int m_iRelocCount; 29 | ImmMap m_imms; 30 | SymbolMap m_syms; 31 | u32 m_dwBase; 32 | u32 m_stubBottom; 33 | bool m_blXmlDump; 34 | 35 | bool FillModule(u8 *pData, u32 iAddr); 36 | bool CreateFakeSections(); 37 | void FreeMemory(); 38 | int LoadSingleImport(PspModuleImport2xx *pImport, u32 addr); 39 | bool LoadImports(); 40 | int LoadSingleExport(PspModuleExport *pExport, u32 addr); 41 | bool LoadExports(); 42 | int CountRelocs(); 43 | int LoadRelocsTypeA(struct ElfReloc *pRelocs); 44 | int LoadRelocsTypeB(struct ElfReloc *pRelocs); 45 | bool LoadRelocs(); 46 | bool BuildMaps(); 47 | void BuildSymbols(); 48 | void FreeSymbols(); 49 | void FreeImms(); 50 | void FixupRelocs(); 51 | bool ReadString(u32 dwAddr, std::string &str, bool unicode, u32 *dwRet); 52 | void DumpStrings(FILE *fp, u32 dwAddr, u32 iSize, unsigned char *pData); 53 | void PrintRow(FILE *fp, const u32* row, s32 row_size, u32 addr); 54 | void DumpData(FILE *fp, u32 dwAddr, u32 iSize, unsigned char *pData); 55 | void Disasm(FILE *fp, u32 dwAddr, u32 iSize, unsigned char *pData, ImmMap &imms); 56 | void DisasmXML(FILE *fp, u32 dwAddr, u32 iSize, unsigned char *pData, ImmMap &imms); 57 | void CalcElfSize(size_t &iTotal, size_t &iSectCount, size_t &iStrSize); 58 | bool OutputElfHeader(FILE *fp, size_t iSectCount); 59 | bool OutputSections(FILE *fp, size_t iElfHeadSize, size_t iSectCount, size_t iStrSize); 60 | 61 | public: 62 | CProcessPrx(u32 dwBase); 63 | virtual ~CProcessPrx(); 64 | virtual bool LoadFromFile(const char *szFilename); 65 | virtual bool LoadFromBinFile(const char *szFilename, unsigned int dwDataBase); 66 | 67 | bool PrxToElf(FILE *fp); 68 | 69 | void SetXmlDump(); 70 | PspModule* GetModuleInfo(); 71 | ElfReloc* GetRelocs(int &iCount); 72 | ElfSymbol* GetSymbols(int &iCount); 73 | PspLibImport *GetImports(); 74 | PspLibExport *GetExports(); 75 | void SetNidMgr(CNidMgr* nidMgr); 76 | void Dump(FILE *fp, const char *disopts); 77 | void DumpXML(FILE *fp, const char *disopts); 78 | SymbolEntry *GetSymbolEntryFromAddr(u32 dwAddr); 79 | }; 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | PRXTool 2 | ======= 3 | This is a simple tool to manipulate Sony PSP(tm) PRX files. Prxtool can: 4 | 5 | * output an IDC file which can be used with IDA Pro 6 | * output an ELF file 7 | * disassemble PRX files into a pretty printed format 8 | 9 | Installation 10 | ------------ 11 | 12 | To compile `prxtool`, run: 13 | 14 | $ ./bootstrap 15 | $ ./configure 16 | $ make 17 | 18 | You can install it by running: 19 | 20 | $ [sudo] make install 21 | 22 | License 23 | ------- 24 | 25 | TyRaNiD (c) 2k6 26 | 27 | PRXTool is licensed under the AFL v2.0. Please read the LICENSE file for further 28 | information. 29 | 30 | Thanks to 31 | 32 | * Mrbrown for adding autoconfig 33 | * all the other people who contribute to legit PSP dev work. 34 | 35 | This is a good companion to libdoc as that provides the XML file used to get 36 | names and such for functions. 37 | 38 | -------------------------------------------------------------------------------- /SerializePrx.C: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | * PRXTool : Utility for PSP executables. 3 | * (c) TyRaNiD 2k5 4 | * 5 | * SerializePrx.C - Implementation of a class to serialize a 6 | * loaded PRX. 7 | ***************************************************************/ 8 | 9 | #include 10 | #include 11 | #include "SerializePrx.h" 12 | #include "output.h" 13 | 14 | CSerializePrx::CSerializePrx() 15 | { 16 | m_blStarted = false; 17 | } 18 | 19 | CSerializePrx::~CSerializePrx() 20 | { 21 | } 22 | 23 | void CSerializePrx::DoSects(CProcessPrx &prx) 24 | { 25 | ElfSection *pSections; 26 | u32 iSects; 27 | u32 iLoop; 28 | 29 | if(StartSects() == false) 30 | { 31 | throw false; 32 | } 33 | 34 | /* We already checked for NULL */ 35 | pSections = prx.ElfGetSections(iSects); 36 | 37 | for(iLoop = 0; iLoop < iSects; iLoop++) 38 | { 39 | if(SerializeSect(iLoop, pSections[iLoop]) == false) 40 | { 41 | throw false; 42 | } 43 | } 44 | 45 | if(EndSects() == false) 46 | { 47 | throw false; 48 | } 49 | } 50 | 51 | void CSerializePrx::DoImports(CProcessPrx &prx) 52 | { 53 | PspModule *pMod; 54 | PspLibImport *pImport; 55 | int iLoop; 56 | 57 | pMod = prx.GetModuleInfo(); 58 | iLoop = 0; 59 | 60 | if(StartImports() == false) 61 | { 62 | throw false; 63 | } 64 | 65 | pImport = pMod->imp_head; 66 | while(pImport != NULL) 67 | { 68 | if(SerializeImport(iLoop, pImport) == false) 69 | { 70 | throw false; 71 | } 72 | 73 | iLoop++; 74 | pImport = pImport->next; 75 | } 76 | 77 | if(EndImports() == false) 78 | { 79 | throw false; 80 | } 81 | } 82 | 83 | void CSerializePrx::DoExports(CProcessPrx &prx, bool blDoSyslib) 84 | { 85 | PspModule *pMod; 86 | PspLibExport *pExport; 87 | int iLoop; 88 | 89 | pMod = prx.GetModuleInfo(); 90 | iLoop = 0; 91 | 92 | if(StartExports() == false) 93 | { 94 | throw false; 95 | } 96 | 97 | pExport = pMod->exp_head; 98 | while(pExport != NULL) 99 | { 100 | if((blDoSyslib) || (strcmp(pExport->name, PSP_SYSTEM_EXPORT) != 0)) 101 | { 102 | if(SerializeExport(iLoop, pExport) == false) 103 | { 104 | throw false; 105 | } 106 | iLoop++; 107 | } 108 | 109 | pExport = pExport->next; 110 | } 111 | 112 | if(EndExports() == false) 113 | { 114 | throw false; 115 | } 116 | } 117 | 118 | void CSerializePrx::DoRelocs(CProcessPrx &prx) 119 | { 120 | ElfReloc* pRelocs; 121 | int iCount; 122 | 123 | if(StartRelocs() == false) 124 | { 125 | throw false; 126 | } 127 | 128 | pRelocs = prx.GetRelocs(iCount); 129 | if(pRelocs != NULL) 130 | { 131 | /* Process the relocs a segment at a time */ 132 | const char *pCurrSec; 133 | int iCurrCount; 134 | 135 | while(iCount > 0) 136 | { 137 | ElfReloc *pBase; 138 | 139 | pBase = pRelocs; 140 | pCurrSec = pRelocs->secname; 141 | iCurrCount = 0; 142 | while((iCount > 0) && (pCurrSec == pRelocs->secname || (pCurrSec != NULL && pRelocs->secname != NULL && (strcmp(pCurrSec, pRelocs->secname) == 0)))) 143 | { 144 | pRelocs++; 145 | iCurrCount++; 146 | iCount--; 147 | } 148 | 149 | if(iCurrCount > 0) 150 | { 151 | if(SerializeReloc(iCurrCount, pBase) == false) 152 | { 153 | throw false; 154 | } 155 | } 156 | } 157 | } 158 | 159 | if(EndRelocs() == false) 160 | { 161 | throw false; 162 | } 163 | } 164 | 165 | bool CSerializePrx::Begin() 166 | { 167 | if(StartFile() == false) 168 | { 169 | return false; 170 | } 171 | 172 | m_blStarted = true; 173 | 174 | return true; 175 | } 176 | 177 | bool CSerializePrx::End() 178 | { 179 | bool blRet = true; 180 | if(m_blStarted == true) 181 | { 182 | blRet = EndFile(); 183 | m_blStarted = false; 184 | } 185 | 186 | return blRet; 187 | } 188 | 189 | bool CSerializePrx::SerializePrx(CProcessPrx &prx, u32 iSMask) 190 | { 191 | bool blRet = false; 192 | 193 | if(m_blStarted == false) 194 | { 195 | if(Begin() != true) 196 | { 197 | COutput::Puts(LEVEL_ERROR, "Failed to begin the serialized output"); 198 | return false; 199 | } 200 | } 201 | 202 | try 203 | { 204 | /* Let's check the prx so we don't have to in the future */ 205 | PspModule *pMod; 206 | u32 iSectNum; 207 | 208 | m_currPrx = &prx; 209 | pMod = prx.GetModuleInfo(); 210 | if(pMod == NULL) 211 | { 212 | COutput::Printf(LEVEL_ERROR, "Invalid module info pMod\n"); 213 | throw false; 214 | } 215 | 216 | if((prx.ElfGetSections(iSectNum) == NULL) && (iSectNum > 0)) 217 | { 218 | COutput::Printf(LEVEL_ERROR, "Invalid section header information\n"); 219 | throw false; 220 | } 221 | 222 | if(StartPrx(prx.GetElfName(), pMod, iSMask) == false) 223 | { 224 | throw false; 225 | } 226 | 227 | if(iSMask & SERIALIZE_SECTIONS) 228 | { 229 | DoSects(prx); 230 | } 231 | 232 | if(iSMask & SERIALIZE_IMPORTS) 233 | { 234 | DoImports(prx); 235 | } 236 | 237 | if(iSMask & SERIALIZE_EXPORTS) 238 | { 239 | DoExports(prx, iSMask & SERIALIZE_DOSYSLIB ? true : false); 240 | } 241 | 242 | if(iSMask & SERIALIZE_RELOCS) 243 | { 244 | DoRelocs(prx); 245 | } 246 | 247 | if(EndPrx() == false) 248 | { 249 | throw false; 250 | } 251 | } 252 | catch(...) 253 | { 254 | /* Do nothing */ 255 | } 256 | 257 | return blRet; 258 | } 259 | -------------------------------------------------------------------------------- /SerializePrx.h: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | * PRXTool : Utility for PSP executables. 3 | * (c) TyRaNiD 2k5 4 | * 5 | * SerializePrx.h - Definition of a class to serialize a PRX. 6 | ***************************************************************/ 7 | 8 | #ifndef __SERIALIZEPRX_H__ 9 | #define __SERIALIZEPRX_H__ 10 | 11 | #include "types.h" 12 | #include "types.h" 13 | #include "ProcessPrx.h" 14 | 15 | enum { 16 | SERIALIZE_IMPORTS = (1 << 0), 17 | SERIALIZE_EXPORTS = (1 << 1), 18 | SERIALIZE_SECTIONS = (1 << 2), 19 | SERIALIZE_RELOCS = (1 << 3), 20 | SERIALIZE_DOSYSLIB = (1 << 4), 21 | SERIALIZE_ALL = 0xFFFFFFFF 22 | }; 23 | 24 | /** Base class for serializing a prx file */ 25 | class CSerializePrx 26 | { 27 | protected: 28 | /** Called when the output file is started */ 29 | virtual bool StartFile() = 0; 30 | /** Called when the output file is ended */ 31 | virtual bool EndFile() = 0; 32 | /** Called when a new prx is about to be serialized */ 33 | virtual bool StartPrx(const char *szFilename, const PspModule *mod, u32 iSMask) = 0; 34 | virtual bool EndPrx() = 0; 35 | /** Called when we are about to start serializing the sections */ 36 | virtual bool StartSects() = 0; 37 | /** Called when we want to serialize a section */ 38 | virtual bool SerializeSect(int index, ElfSection §) = 0; 39 | /** Called when have finished serializing the sections */ 40 | virtual bool EndSects() = 0; 41 | virtual bool StartImports() = 0; 42 | virtual bool SerializeImport(int index, const PspLibImport *imp) = 0; 43 | virtual bool EndImports() = 0; 44 | virtual bool StartExports() = 0; 45 | virtual bool SerializeExport(int index, const PspLibExport *exp) = 0; 46 | virtual bool EndExports() = 0; 47 | virtual bool StartRelocs() = 0; 48 | /* Called with a list of relocs for a single segment */ 49 | virtual bool SerializeReloc(int count, const ElfReloc *rel) = 0; 50 | virtual bool EndRelocs() = 0; 51 | 52 | /** Pointer to the current prx, if the functions need it for what ever reason */ 53 | CProcessPrx* m_currPrx; 54 | bool m_blStarted; 55 | 56 | void DoSects(CProcessPrx &prx); 57 | void DoImports(CProcessPrx &prx); 58 | void DoExports(CProcessPrx &prx, bool blDoSyslib); 59 | void DoRelocs(CProcessPrx &prx); 60 | public: 61 | CSerializePrx(); 62 | virtual ~CSerializePrx(); 63 | bool Begin(); 64 | bool SerializePrx(CProcessPrx &prx, u32 iSMask); 65 | bool End(); 66 | }; 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /SerializePrxToIdc.C: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | * PRXTool : Utility for PSP executables. 3 | * (c) TyRaNiD 2k5 4 | * 5 | * SerializePrxToIdc.C - Implementation of a class to serialize 6 | * a loaded PRX file to a IDA PRO IDC file. 7 | ***************************************************************/ 8 | 9 | #include 10 | #include "SerializePrxToIdc.h" 11 | 12 | /* Build a name from a base and extention */ 13 | static const char *BuildName(const char* base, const char *ext) 14 | { 15 | static char str_export[512]; 16 | 17 | snprintf(str_export, sizeof(str_export), "%s_%s", base, ext); 18 | 19 | return str_export; 20 | } 21 | 22 | /* Make a name for the idc */ 23 | static void MakeName(FILE *fp, const char *str, unsigned int addr) 24 | { 25 | fprintf(fp, " MakeName(0x%08X, \"%s\");\n", addr, str); 26 | } 27 | 28 | /* Max a string for the idc */ 29 | static void MakeString(FILE *fp, const char *str, unsigned int addr) 30 | { 31 | MakeName(fp, str, addr); 32 | fprintf(fp, " MakeStr(0x%08X, BADADDR);\n", addr); 33 | } 34 | 35 | /* Make a dword for the idc */ 36 | static void MakeDword(FILE *fp, const char*str, unsigned int addr) 37 | { 38 | MakeName(fp, str, addr); 39 | fprintf(fp, " MakeDword(0x%08X);\n", addr); 40 | } 41 | 42 | /* Make an offset for the idc */ 43 | static void MakeOffset(FILE *fp, const char *str, unsigned int addr) 44 | { 45 | MakeDword(fp, str, addr); 46 | fprintf(fp, " OpOff(0x%08X, 0, 0);\n", addr); 47 | } 48 | 49 | /* Make a function for the idc */ 50 | static void MakeFunction(FILE *fp, const char *str, unsigned int addr) 51 | { 52 | MakeName(fp, str, addr); 53 | fprintf(fp, " MakeFunction(0x%08X, BADADDR);\n", addr); 54 | } 55 | 56 | CSerializePrxToIdc::CSerializePrxToIdc(FILE *fpOut) 57 | { 58 | m_fpOut = fpOut; 59 | } 60 | 61 | CSerializePrxToIdc::~CSerializePrxToIdc() 62 | { 63 | fflush(m_fpOut); 64 | } 65 | 66 | bool CSerializePrxToIdc::StartFile() 67 | { 68 | return true; 69 | } 70 | 71 | bool CSerializePrxToIdc::EndFile() 72 | { 73 | /* Do nothing */ 74 | return true; 75 | } 76 | 77 | bool CSerializePrxToIdc::StartPrx(const char* szFilename, const PspModule *mod, u32 iSMask) 78 | { 79 | u32 addr; 80 | 81 | fprintf(m_fpOut, "#include \n\n"); 82 | fprintf(m_fpOut, "static main() {\n"); 83 | if(iSMask & SERIALIZE_SECTIONS) 84 | { 85 | fprintf(m_fpOut, " createSegments();\n"); 86 | } 87 | fprintf(m_fpOut, " createModuleInfo();\n"); 88 | if(iSMask & SERIALIZE_EXPORTS) 89 | { 90 | fprintf(m_fpOut, " createExports(); \n"); 91 | } 92 | if(iSMask & SERIALIZE_IMPORTS) 93 | { 94 | fprintf(m_fpOut, " createImports(); \n"); 95 | } 96 | if(iSMask & SERIALIZE_RELOCS) 97 | { 98 | fprintf(m_fpOut, " createRelocs(); \n"); 99 | } 100 | fprintf(m_fpOut, "}\n\n"); 101 | 102 | fprintf(m_fpOut, "static createModuleInfo() {\n"); 103 | 104 | addr = mod->addr; 105 | 106 | MakeDword(m_fpOut, "_module_flags", addr); 107 | MakeString(m_fpOut, "_module_name", addr+4); 108 | MakeDword(m_fpOut, "_module_gp", addr+32); 109 | MakeOffset(m_fpOut, "_module_exports", addr+36); 110 | MakeOffset(m_fpOut, "_module_exp_end", addr+40); 111 | MakeOffset(m_fpOut, "_module_imports", addr+44); 112 | MakeOffset(m_fpOut, "_module_imp_end", addr+48); 113 | 114 | fprintf(m_fpOut, "}\n\n"); 115 | 116 | return true; 117 | } 118 | 119 | bool CSerializePrxToIdc::EndPrx() 120 | { 121 | /* Do nothing */ 122 | return true; 123 | } 124 | 125 | bool CSerializePrxToIdc::StartSects() 126 | { 127 | fprintf(m_fpOut, "static createSegments() {\n"); 128 | return true; 129 | } 130 | 131 | bool CSerializePrxToIdc::SerializeSect(int num, ElfSection §) 132 | { 133 | u32 shFlags; 134 | u32 shType; 135 | u32 shAddr; 136 | u32 shSize; 137 | const char *pName; 138 | 139 | shFlags = sect.iFlags; 140 | shType = sect.iType; 141 | shAddr = sect.iAddr; 142 | shSize = sect.iSize; 143 | pName = sect.szName; 144 | 145 | /* Check if the section is loadable */ 146 | if((shFlags & SHF_ALLOC) && ((shType == SHT_PROGBITS) || (shType == SHT_NOBITS))) 147 | { 148 | fprintf(m_fpOut, " SegCreate(0x%08X, 0x%08X, 0, 1, 1, 2);\n", 149 | shAddr, shAddr + shSize); 150 | fprintf(m_fpOut, " SegRename(0x%08X, \"%s\");\n", shAddr, pName); 151 | fprintf(m_fpOut, " SegClass(0x%08X, \"CODE\");\n", shAddr); 152 | if(shFlags & SHF_EXECINSTR) 153 | { 154 | fprintf(m_fpOut, " SetSegmentType(0x%08X, SEG_CODE);\n", shAddr); 155 | } 156 | else 157 | { 158 | if(shType == SHT_NOBITS) 159 | { 160 | fprintf(m_fpOut, " SetSegmentType(0x%08X, SEG_BSS);\n", shAddr); 161 | } 162 | else 163 | { 164 | fprintf(m_fpOut, " SetSegmentType(0x%08X, SEG_DATA);\n", shAddr); 165 | } 166 | } 167 | } 168 | 169 | return true; 170 | } 171 | 172 | bool CSerializePrxToIdc::EndSects() 173 | { 174 | fprintf(m_fpOut, "}\n\n"); 175 | return true; 176 | } 177 | 178 | bool CSerializePrxToIdc::StartImports() 179 | { 180 | fprintf(m_fpOut, "static createImports() {\n"); 181 | return true; 182 | } 183 | 184 | bool CSerializePrxToIdc::SerializeImport(int num, const PspLibImport *imp) 185 | { 186 | char str_import[128]; 187 | int iLoop; 188 | u32 addr; 189 | snprintf(str_import, sizeof(str_import), "import%d", num); 190 | 191 | addr = imp->addr; 192 | 193 | if(imp->stub.name != 0) 194 | { 195 | MakeOffset(m_fpOut, str_import, addr); 196 | MakeString(m_fpOut, BuildName(str_import, "name"), imp->stub.name); 197 | } 198 | else 199 | { 200 | MakeDword(m_fpOut, str_import, addr); 201 | } 202 | 203 | MakeDword(m_fpOut, BuildName(str_import, "flags"), addr+4); 204 | MakeDword(m_fpOut, BuildName(str_import, "counts"), addr+8); 205 | MakeOffset(m_fpOut, BuildName(str_import, "nids"), addr+12); 206 | MakeOffset(m_fpOut, BuildName(str_import, "funcs"), addr+16); 207 | 208 | for(iLoop = 0; iLoop < imp->f_count; iLoop++) 209 | { 210 | MakeDword(m_fpOut, BuildName(str_import, imp->funcs[iLoop].name), imp->funcs[iLoop].nid_addr); 211 | MakeFunction(m_fpOut, imp->funcs[iLoop].name, imp->funcs[iLoop].addr); 212 | } 213 | 214 | for(iLoop = 0; iLoop < imp->v_count; iLoop++) 215 | { 216 | MakeDword(m_fpOut, BuildName(str_import, imp->vars[iLoop].name), imp->vars[iLoop].nid_addr); 217 | MakeOffset(m_fpOut, "", imp->vars[iLoop].nid_addr + ((imp->v_count + imp->f_count) * 4)); 218 | } 219 | 220 | return true; 221 | } 222 | 223 | bool CSerializePrxToIdc::EndImports() 224 | { 225 | fprintf(m_fpOut, "}\n\n"); 226 | return true; 227 | } 228 | 229 | bool CSerializePrxToIdc::StartExports() 230 | { 231 | fprintf(m_fpOut, "static createExports() {\n"); 232 | return true; 233 | } 234 | 235 | bool CSerializePrxToIdc::SerializeExport(int num, const PspLibExport *exp) 236 | { 237 | char str_export[128]; 238 | int iLoop; 239 | u32 addr; 240 | snprintf(str_export, sizeof(str_export), "export_%d", num); 241 | 242 | addr = exp->addr; 243 | 244 | if(exp->stub.name != 0) 245 | { 246 | MakeOffset(m_fpOut, str_export, addr); 247 | MakeString(m_fpOut, BuildName(str_export, "name"), exp->stub.name); 248 | } 249 | else 250 | { 251 | MakeDword(m_fpOut, str_export, addr); 252 | } 253 | 254 | MakeDword(m_fpOut, BuildName(str_export, "flags"), addr+4); 255 | MakeDword(m_fpOut, BuildName(str_export, "counts"), addr+8); 256 | MakeOffset(m_fpOut, BuildName(str_export, "exports"), addr+12); 257 | 258 | for(iLoop = 0; iLoop < exp->f_count; iLoop++) 259 | { 260 | MakeDword(m_fpOut, BuildName(str_export, exp->funcs[iLoop].name), exp->funcs[iLoop].nid_addr); 261 | MakeOffset(m_fpOut, "", exp->funcs[iLoop].nid_addr + ((exp->v_count + exp->f_count) * 4)); 262 | MakeFunction(m_fpOut, exp->funcs[iLoop].name, exp->funcs[iLoop].addr); 263 | } 264 | 265 | for(iLoop = 0; iLoop < exp->v_count; iLoop++) 266 | { 267 | MakeDword(m_fpOut, BuildName(str_export, exp->vars[iLoop].name), exp->vars[iLoop].nid_addr); 268 | MakeOffset(m_fpOut, "", exp->vars[iLoop].nid_addr + ((exp->v_count + exp->f_count) * 4)); 269 | } 270 | 271 | return true; 272 | } 273 | 274 | bool CSerializePrxToIdc::EndExports() 275 | { 276 | fprintf(m_fpOut, "}\n\n"); 277 | return true; 278 | } 279 | 280 | bool CSerializePrxToIdc::StartRelocs() 281 | { 282 | fprintf(m_fpOut, "static createRelocs() {\n"); 283 | return true; 284 | } 285 | 286 | bool CSerializePrxToIdc::SerializeReloc(int count, const ElfReloc *rel) 287 | { 288 | ElfSection *pDataSect, *pTextSect; 289 | 290 | pDataSect = m_currPrx->ElfFindSection(".data"); 291 | pTextSect = m_currPrx->ElfFindSection(".text"); 292 | 293 | fprintf(stderr, "Reloc count %d, %s, data %p, text %p\n", count, rel->secname, pDataSect, pTextSect); 294 | return true; 295 | } 296 | 297 | bool CSerializePrxToIdc::EndRelocs() 298 | { 299 | fprintf(m_fpOut, "}\n\n"); 300 | return true; 301 | } 302 | 303 | -------------------------------------------------------------------------------- /SerializePrxToIdc.h: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | * PRXTool : Utility for PSP executables. 3 | * (c) TyRaNiD 2k5 4 | * 5 | * SerializePrxToIdc.h - Definition of a class to serialize a 6 | * PRX to an IDA Pro IDC file. 7 | ***************************************************************/ 8 | 9 | #ifndef __SERIALIZEPRXTOIDC_H__ 10 | #define __SERIALIZEPRXTOIDC_H__ 11 | 12 | #include 13 | #include "SerializePrx.h" 14 | 15 | class CSerializePrxToIdc : public CSerializePrx 16 | { 17 | FILE *m_fpOut; 18 | 19 | virtual bool StartFile(); 20 | virtual bool EndFile(); 21 | virtual bool StartPrx(const char *szFilename, const PspModule *pMod, u32 iSMask); 22 | virtual bool EndPrx(); 23 | virtual bool StartSects(); 24 | virtual bool SerializeSect(int num, ElfSection §); 25 | virtual bool EndSects(); 26 | virtual bool StartImports(); 27 | virtual bool SerializeImport(int num, const PspLibImport *imp); 28 | virtual bool EndImports(); 29 | virtual bool StartExports(); 30 | virtual bool SerializeExport(int num, const PspLibExport *exp); 31 | virtual bool EndExports(); 32 | virtual bool StartRelocs(); 33 | virtual bool SerializeReloc(int count, const ElfReloc *rel); 34 | virtual bool EndRelocs(); 35 | 36 | public: 37 | CSerializePrxToIdc(FILE *fpOut); 38 | ~CSerializePrxToIdc(); 39 | }; 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /SerializePrxToMap.C: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | * PRXTool : Utility for PSP executables. 3 | * (c) TyRaNiD 2k5 4 | * 5 | * SerializePrxToMap.C - Implementation of a class to serialize 6 | * a loaded PRX file to a PS2DIS Map file. 7 | ***************************************************************/ 8 | 9 | #include 10 | #include "SerializePrxToMap.h" 11 | 12 | /* Build a name from a base and extention */ 13 | static const char *BuildName(const char* base, const char *ext) 14 | { 15 | static char str_export[512]; 16 | 17 | snprintf(str_export, sizeof(str_export), "%s_%s", base, ext); 18 | 19 | return str_export; 20 | } 21 | 22 | static void PrintOffset(FILE *fp, unsigned int addr) 23 | { 24 | fprintf(fp, "%08x:\n", addr); 25 | } 26 | 27 | static void PrintComment(FILE *fp, const char *text) 28 | { 29 | fprintf(fp, "# %s\n", text); 30 | } 31 | 32 | CSerializePrxToMap::CSerializePrxToMap(FILE *fpOut) 33 | { 34 | m_fpOut = fpOut; 35 | } 36 | 37 | CSerializePrxToMap::~CSerializePrxToMap() 38 | { 39 | fflush(m_fpOut); 40 | } 41 | 42 | bool CSerializePrxToMap::StartFile() 43 | { 44 | return true; 45 | } 46 | 47 | bool CSerializePrxToMap::EndFile() 48 | { 49 | /* Do nothing */ 50 | return true; 51 | } 52 | 53 | bool CSerializePrxToMap::StartPrx(const char* szFilename, const PspModule *mod, u32 iSMask) 54 | { 55 | u32 i; 56 | u32 addr; 57 | 58 | PrintComment(m_fpOut, "Generated by prxtool"); 59 | PrintComment(m_fpOut, "Make sure to \"Load From Address 0xA0\" to skip the ELF header"); 60 | PrintComment(m_fpOut, "Make sure to load the module as plain binary, not as ELF"); 61 | fprintf(m_fpOut, "# File: %s\n", szFilename); 62 | 63 | addr = mod->addr; 64 | 65 | PrintOffset(m_fpOut, addr); 66 | fprintf(m_fpOut, ".word\t_module_flags\n"); 67 | fprintf(m_fpOut, ".byte\t_module_name\n"); 68 | for(i=0; i < (sizeof(mod->name)-2); i++) 69 | fprintf(m_fpOut, ".byte\n"); 70 | fprintf(m_fpOut, ".word\t_module_gp\n"); 71 | fprintf(m_fpOut, ".word\t_module_exports\n"); 72 | fprintf(m_fpOut, ".word\t_module_exp_end\n"); 73 | fprintf(m_fpOut, ".word\t_module_imports\n"); 74 | fprintf(m_fpOut, ".word\t_module_imp_end\n"); 75 | 76 | return true; 77 | } 78 | 79 | bool CSerializePrxToMap::EndPrx() 80 | { 81 | /* Do nothing */ 82 | return true; 83 | } 84 | 85 | bool CSerializePrxToMap::StartSects() 86 | { 87 | /* Do nothing */ 88 | return true; 89 | } 90 | 91 | bool CSerializePrxToMap::SerializeSect(int num, ElfSection §) 92 | { 93 | u32 shFlags; 94 | u32 shType; 95 | u32 shAddr; 96 | u32 shSize; 97 | const char *pName; 98 | 99 | shFlags = sect.iFlags; 100 | shType = sect.iType; 101 | shAddr = sect.iAddr; 102 | shSize = sect.iSize; 103 | pName = sect.szName; 104 | 105 | /* Check if the section is loadable */ 106 | if((shFlags & SHF_ALLOC) && ((shType == SHT_PROGBITS) || (shType == SHT_NOBITS))) 107 | { 108 | PrintOffset(m_fpOut, shAddr); 109 | fprintf(m_fpOut, ".word\t%s\t;", pName); 110 | 111 | if(shFlags & SHF_EXECINSTR) 112 | { 113 | fprintf(m_fpOut, " SEG_CODE"); 114 | } 115 | else 116 | { 117 | if(shType == SHT_NOBITS) 118 | { 119 | fprintf(m_fpOut, " SEG_BSS"); 120 | } 121 | else 122 | { 123 | fprintf(m_fpOut, " SEG_DATA"); 124 | } 125 | } 126 | 127 | fprintf(m_fpOut, " 0x%08x - 0x%08x\n", shAddr, shAddr + shSize); 128 | } 129 | 130 | return true; 131 | } 132 | 133 | bool CSerializePrxToMap::EndSects() 134 | { 135 | return true; 136 | } 137 | 138 | bool CSerializePrxToMap::StartImports() 139 | { 140 | return true; 141 | } 142 | 143 | bool CSerializePrxToMap::SerializeImport(int num, const PspLibImport *imp) 144 | { 145 | char str_import[128]; 146 | int iLoop; 147 | u32 addr; 148 | snprintf(str_import, sizeof(str_import), "import%d", num); 149 | 150 | addr = imp->addr; 151 | 152 | if(imp->stub.name != 0) 153 | { 154 | PrintOffset(m_fpOut, addr); 155 | fprintf(m_fpOut, ".word\t%s\t; %s\n", imp->name, BuildName(str_import, "name")); 156 | } 157 | else 158 | { 159 | PrintOffset(m_fpOut, addr); 160 | fprintf(m_fpOut, ".word\t%s\t; %s\n", str_import, BuildName(str_import, "name")); 161 | } 162 | 163 | fprintf(m_fpOut, ".word\t%s\n", BuildName(str_import, "flags")); 164 | fprintf(m_fpOut, ".word\t%s\n", BuildName(str_import, "counts")); 165 | fprintf(m_fpOut, ".word\t%s\n", BuildName(str_import, "nids")); 166 | fprintf(m_fpOut, ".word\t%s\n", BuildName(str_import, "funcs")); 167 | 168 | for(iLoop = 0; iLoop < imp->f_count; iLoop++) 169 | { 170 | PrintOffset(m_fpOut, imp->funcs[iLoop].nid_addr); 171 | fprintf(m_fpOut, ".word\t%s\t; NID %08x\n", BuildName(str_import, imp->funcs[iLoop].name), imp->funcs[iLoop].nid); 172 | 173 | PrintOffset(m_fpOut, imp->funcs[iLoop].addr); 174 | fprintf(m_fpOut, ".code\t%s\n", imp->funcs[iLoop].name); 175 | } 176 | 177 | for(iLoop = 0; iLoop < imp->v_count; iLoop++) 178 | { 179 | 180 | PrintOffset(m_fpOut, imp->funcs[iLoop].nid_addr); 181 | fprintf(m_fpOut, ".word\t%s\t; NID %08x\n", BuildName(str_import, imp->vars[iLoop].name), imp->vars[iLoop].nid); 182 | 183 | PrintOffset(m_fpOut, imp->vars[iLoop].nid_addr + ((imp->v_count + imp->f_count) * 4)); 184 | fprintf(m_fpOut, ".word\t%s\n", imp->vars[iLoop].name); 185 | } 186 | 187 | return true; 188 | } 189 | 190 | bool CSerializePrxToMap::EndImports() 191 | { 192 | return true; 193 | } 194 | 195 | bool CSerializePrxToMap::StartExports() 196 | { 197 | return true; 198 | } 199 | 200 | bool CSerializePrxToMap::SerializeExport(int num, const PspLibExport *exp) 201 | { 202 | char str_export[128]; 203 | int iLoop; 204 | u32 addr; 205 | snprintf(str_export, sizeof(str_export), "export_%d", num); 206 | 207 | addr = exp->addr; 208 | 209 | if(exp->stub.name != 0) 210 | { 211 | PrintOffset(m_fpOut, addr); 212 | fprintf(m_fpOut, ".word\t%s\t; %s\n", exp->name, BuildName(str_export, "name")); 213 | } 214 | else 215 | { 216 | PrintOffset(m_fpOut, addr); 217 | fprintf(m_fpOut, ".word\t%s\t; %s\n", str_export, BuildName(str_export, "name")); 218 | } 219 | 220 | fprintf(m_fpOut, ".word\t%s\n", BuildName(str_export, "flags")); 221 | fprintf(m_fpOut, ".word\t%s\n", BuildName(str_export, "counts")); 222 | fprintf(m_fpOut, ".word\t%s\n", BuildName(str_export, "exports")); 223 | 224 | for(iLoop = 0; iLoop < exp->f_count; iLoop++) 225 | { 226 | PrintOffset(m_fpOut, exp->funcs[iLoop].nid_addr); 227 | fprintf(m_fpOut, ".word\t%s\t; NID %08x\n", BuildName(str_export, exp->funcs[iLoop].name), exp->funcs[iLoop].nid); 228 | 229 | PrintOffset(m_fpOut, exp->funcs[iLoop].nid_addr + ((exp->v_count + exp->f_count) * 4)); 230 | fprintf(m_fpOut, ".word\n"); 231 | 232 | PrintOffset(m_fpOut, exp->funcs[iLoop].addr); 233 | fprintf(m_fpOut, ".code\t%s\n", exp->funcs[iLoop].name); 234 | } 235 | 236 | for(iLoop = 0; iLoop < exp->v_count; iLoop++) 237 | { 238 | PrintOffset(m_fpOut, exp->funcs[iLoop].nid_addr); 239 | fprintf(m_fpOut, ".word\t%s\t; NID %08x\n", BuildName(str_export, exp->vars[iLoop].name), exp->vars[iLoop].nid); 240 | 241 | PrintOffset(m_fpOut, exp->vars[iLoop].nid_addr + ((exp->v_count + exp->f_count) * 4)); 242 | fprintf(m_fpOut, ".word\t%s\n", exp->vars[iLoop].name); 243 | } 244 | 245 | return true; 246 | } 247 | 248 | bool CSerializePrxToMap::EndExports() 249 | { 250 | return true; 251 | } 252 | 253 | bool CSerializePrxToMap::StartRelocs() 254 | { 255 | return true; 256 | } 257 | 258 | bool CSerializePrxToMap::SerializeReloc(int count, const ElfReloc *rel) 259 | { 260 | ElfSection *pDataSect, *pTextSect; 261 | 262 | pDataSect = m_currPrx->ElfFindSection(".data"); 263 | pTextSect = m_currPrx->ElfFindSection(".text"); 264 | 265 | fprintf(stderr, "Reloc count %d, %s, data %p, text %p\n", count, rel->secname, pDataSect, pTextSect); 266 | return true; 267 | } 268 | 269 | bool CSerializePrxToMap::EndRelocs() 270 | { 271 | return true; 272 | } 273 | 274 | -------------------------------------------------------------------------------- /SerializePrxToMap.h: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | * PRXTool : Utility for PSP executables. 3 | * (c) TyRaNiD 2k5 4 | * 5 | * SerializePrxToMap.h - Implementation of a class to serialize 6 | * a loaded PRX file to a PS2DIS Map file. 7 | ***************************************************************/ 8 | 9 | #ifndef __SERIALIZEPRXTOMAP_H__ 10 | #define __SERIALIZEPRXTOMAP_H__ 11 | 12 | #include 13 | #include "SerializePrx.h" 14 | 15 | class CSerializePrxToMap : public CSerializePrx 16 | { 17 | FILE *m_fpOut; 18 | 19 | virtual bool StartFile(); 20 | virtual bool EndFile(); 21 | virtual bool StartPrx(const char *szFilename, const PspModule *pMod, u32 iSMask); 22 | virtual bool EndPrx(); 23 | virtual bool StartSects(); 24 | virtual bool SerializeSect(int num, ElfSection §); 25 | virtual bool EndSects(); 26 | virtual bool StartImports(); 27 | virtual bool SerializeImport(int num, const PspLibImport *imp); 28 | virtual bool EndImports(); 29 | virtual bool StartExports(); 30 | virtual bool SerializeExport(int num, const PspLibExport *exp); 31 | virtual bool EndExports(); 32 | virtual bool StartRelocs(); 33 | virtual bool SerializeReloc(int count, const ElfReloc *rel); 34 | virtual bool EndRelocs(); 35 | 36 | public: 37 | CSerializePrxToMap(FILE *fpOut); 38 | ~CSerializePrxToMap(); 39 | }; 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /SerializePrxToXml.C: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | * PRXTool : Utility for PSP executables. 3 | * (c) TyRaNiD 2k5 4 | * 5 | * SerializePrxToXml.C - Implementation of a class to serialize 6 | * a loaded PRX to an XML file. 7 | ***************************************************************/ 8 | 9 | #include 10 | #include "SerializePrxToXml.h" 11 | 12 | CSerializePrxToXml::CSerializePrxToXml(FILE *fpOut) 13 | { 14 | m_fpOut = fpOut; 15 | } 16 | 17 | CSerializePrxToXml::~CSerializePrxToXml() 18 | { 19 | fflush(m_fpOut); 20 | } 21 | 22 | bool CSerializePrxToXml::StartFile() 23 | { 24 | fprintf(m_fpOut, "\n"); 25 | fprintf(m_fpOut, "\n"); 26 | fprintf(m_fpOut, "\n"); 27 | fprintf(m_fpOut, "\t\n"); 28 | 29 | return true; 30 | } 31 | 32 | bool CSerializePrxToXml::EndFile() 33 | { 34 | fprintf(m_fpOut, "\t\n"); 35 | fprintf(m_fpOut, "\n"); 36 | return true; 37 | } 38 | 39 | bool CSerializePrxToXml::StartPrx(const char *szFilename, const PspModule *mod, u32 iSMask) 40 | { 41 | fprintf(m_fpOut, "\t\t\n"); 42 | fprintf(m_fpOut, "\t\t%s\n", szFilename); 43 | fprintf(m_fpOut, "\t\t%s\n", mod->name); 44 | fprintf(m_fpOut, "\t\t\n"); 45 | return true; 46 | } 47 | 48 | bool CSerializePrxToXml::EndPrx() 49 | { 50 | fprintf(m_fpOut, "\t\t\n"); 51 | fprintf(m_fpOut, "\t\t\n"); 52 | return true; 53 | } 54 | 55 | bool CSerializePrxToXml::StartSects() 56 | { 57 | /* Do nothing for this in XML */ 58 | return true; 59 | } 60 | 61 | bool CSerializePrxToXml::SerializeSect(int num, ElfSection §) 62 | { 63 | /* Do nothing for this in XML */ 64 | 65 | return true; 66 | } 67 | 68 | bool CSerializePrxToXml::EndSects() 69 | { 70 | /* Do nothing for this in XML */ 71 | return true; 72 | } 73 | 74 | bool CSerializePrxToXml::StartImports() 75 | { 76 | return true; 77 | } 78 | 79 | bool CSerializePrxToXml::SerializeImport(int num, const PspLibImport *imp) 80 | { 81 | int iLoop; 82 | 83 | fprintf(m_fpOut, "\t\t\t\n"); 84 | fprintf(m_fpOut, "\t\t\t\t%s\n", imp->name); 85 | fprintf(m_fpOut, "\t\t\t\t0x%08X\n", imp->stub.flags); 86 | 87 | if(imp->f_count > 0) 88 | { 89 | fprintf(m_fpOut, "\t\t\t\t\n"); 90 | 91 | for(iLoop = 0; iLoop < imp->f_count; iLoop++) 92 | { 93 | fprintf(m_fpOut, "\t\t\t\t\t\n"); 94 | fprintf(m_fpOut, "\t\t\t\t\t\t0x%08X\n", imp->funcs[iLoop].nid); 95 | fprintf(m_fpOut, "\t\t\t\t\t\t%s\n", imp->funcs[iLoop].name); 96 | fprintf(m_fpOut, "\t\t\t\t\t\n"); 97 | } 98 | 99 | fprintf(m_fpOut, "\t\t\t\t\n"); 100 | } 101 | 102 | 103 | if(imp->v_count > 0) 104 | { 105 | fprintf(m_fpOut, "\t\t\t\t\n"); 106 | 107 | for(iLoop = 0; iLoop < imp->v_count; iLoop++) 108 | { 109 | fprintf(m_fpOut, "\t\t\t\t\t\n"); 110 | fprintf(m_fpOut, "\t\t\t\t\t\t0x%08X\n", imp->vars[iLoop].nid); 111 | fprintf(m_fpOut, "\t\t\t\t\t\t%s\n", imp->vars[iLoop].name); 112 | fprintf(m_fpOut, "\t\t\t\t\t\n"); 113 | } 114 | fprintf(m_fpOut, "\t\t\t\t\n"); 115 | } 116 | 117 | fprintf(m_fpOut, "\t\t\t\n"); 118 | 119 | return true; 120 | } 121 | 122 | bool CSerializePrxToXml::EndImports() 123 | { 124 | return true; 125 | } 126 | 127 | bool CSerializePrxToXml::StartExports() 128 | { 129 | return true; 130 | } 131 | 132 | bool CSerializePrxToXml::SerializeExport(int num, const PspLibExport *exp) 133 | { 134 | int iLoop; 135 | 136 | fprintf(m_fpOut, "\t\t\t\n"); 137 | fprintf(m_fpOut, "\t\t\t\t%s\n", exp->name); 138 | fprintf(m_fpOut, "\t\t\t\t0x%08X\n", exp->stub.flags); 139 | 140 | if(exp->f_count > 0) 141 | { 142 | fprintf(m_fpOut, "\t\t\t\t\n"); 143 | 144 | for(iLoop = 0; iLoop < exp->f_count; iLoop++) 145 | { 146 | fprintf(m_fpOut, "\t\t\t\t\t\n"); 147 | fprintf(m_fpOut, "\t\t\t\t\t\t0x%08X\n", exp->funcs[iLoop].nid); 148 | fprintf(m_fpOut, "\t\t\t\t\t\t%s\n", exp->funcs[iLoop].name); 149 | fprintf(m_fpOut, "\t\t\t\t\t\n"); 150 | } 151 | 152 | fprintf(m_fpOut, "\t\t\t\t\n"); 153 | } 154 | 155 | 156 | if(exp->v_count > 0) 157 | { 158 | fprintf(m_fpOut, "\t\t\t\t\n"); 159 | for(iLoop = 0; iLoop < exp->v_count; iLoop++) 160 | { 161 | fprintf(m_fpOut, "\t\t\t\t\t\n"); 162 | fprintf(m_fpOut, "\t\t\t\t\t\t0x%08X\n", exp->vars[iLoop].nid); 163 | fprintf(m_fpOut, "\t\t\t\t\t\t%s\n", exp->vars[iLoop].name); 164 | fprintf(m_fpOut, "\t\t\t\t\t\n"); 165 | } 166 | fprintf(m_fpOut, "\t\t\t\t\n"); 167 | } 168 | 169 | fprintf(m_fpOut, "\t\t\t\n"); 170 | 171 | return true; 172 | } 173 | 174 | bool CSerializePrxToXml::EndExports() 175 | { 176 | return true; 177 | } 178 | 179 | bool CSerializePrxToXml::StartRelocs() 180 | { 181 | return true; 182 | } 183 | 184 | bool CSerializePrxToXml::SerializeReloc(int count, const ElfReloc *rel) 185 | { 186 | return true; 187 | } 188 | 189 | bool CSerializePrxToXml::EndRelocs() 190 | { 191 | return true; 192 | } 193 | 194 | -------------------------------------------------------------------------------- /SerializePrxToXml.h: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | * PRXTool : Utility for PSP executables. 3 | * (c) TyRaNiD 2k5 4 | * 5 | * SerializePrxToXml.h - Definition of a class to serialize a 6 | * PRX to an XML file. 7 | ***************************************************************/ 8 | 9 | #ifndef __SERIALIZEPRXTOXML_H__ 10 | #define __SERIALIZEPRXTOXML_H__ 11 | 12 | #include 13 | #include "SerializePrx.h" 14 | 15 | class CSerializePrxToXml : public CSerializePrx 16 | { 17 | FILE *m_fpOut; 18 | 19 | virtual bool StartFile(); 20 | virtual bool EndFile(); 21 | virtual bool StartPrx(const char *szFilename, const PspModule *mod, u32 iSMask); 22 | virtual bool EndPrx(); 23 | virtual bool StartSects(); 24 | virtual bool SerializeSect(int num, ElfSection §); 25 | virtual bool EndSects(); 26 | virtual bool StartImports(); 27 | virtual bool SerializeImport(int num, const PspLibImport *imp); 28 | virtual bool EndImports(); 29 | virtual bool StartExports(); 30 | virtual bool SerializeExport(int num, const PspLibExport *exp); 31 | virtual bool EndExports(); 32 | virtual bool StartRelocs(); 33 | virtual bool SerializeReloc(int count, const ElfReloc *rel); 34 | virtual bool EndRelocs(); 35 | 36 | public: 37 | CSerializePrxToXml(FILE *fpOut); 38 | ~CSerializePrxToXml(); 39 | }; 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /VirtualMem.C: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | * PRXTool : Utility for PSP executables. 3 | * (c) TyRaNiD 2k5 4 | * 5 | * VirtualMem.C - An implementation of a class to virtualise 6 | * a memory space. 7 | ***************************************************************/ 8 | 9 | #include 10 | #include 11 | #include "VirtualMem.h" 12 | #include "output.h" 13 | 14 | #define CHECK_ADDR(addr, size) ((check_addr(addr, size, m_iBaseAddr, m_iSize)) && (m_pData != NULL)) 15 | 16 | inline bool check_addr(u32 addr, u32 size, u32 baseaddr, u32 basesize) 17 | { 18 | if(addr >= baseaddr) 19 | { 20 | if((addr + size) < (baseaddr + basesize)) 21 | { 22 | return true; 23 | } 24 | } 25 | 26 | return false; 27 | } 28 | 29 | CVirtualMem::CVirtualMem() 30 | { 31 | m_pData = NULL; 32 | m_iSize = 0; 33 | m_iBaseAddr = 0; 34 | m_endian = MEM_LITTLE_ENDIAN; 35 | } 36 | 37 | CVirtualMem::CVirtualMem(u8 *pData, u32 iSize, u32 iBaseAddr, MemEndian endian) 38 | { 39 | m_pData = pData; 40 | m_iSize = iSize; 41 | m_iBaseAddr = iBaseAddr; 42 | m_endian = endian; 43 | COutput::Printf(LEVEL_DEBUG, "pData %p, iSize %x, iBaseAddr 0x%08X, endian %d\n", 44 | pData, iSize, iBaseAddr, endian); 45 | } 46 | 47 | CVirtualMem::~CVirtualMem() 48 | { 49 | /* Do nothing */ 50 | } 51 | 52 | u8 CVirtualMem::GetU8(u32 iAddr) 53 | { 54 | if(CHECK_ADDR(iAddr, 1)) 55 | { 56 | return m_pData[iAddr - m_iBaseAddr]; 57 | } 58 | 59 | COutput::Printf(LEVEL_DEBUG, "Invalid memory address 0x%08X\n", iAddr); 60 | return 0; 61 | } 62 | 63 | u16 CVirtualMem::GetU16(u32 iAddr) 64 | { 65 | if(CHECK_ADDR(iAddr, 2)) 66 | { 67 | if(m_endian == MEM_LITTLE_ENDIAN) 68 | { 69 | return LH_LE(*((u16*) &m_pData[iAddr - m_iBaseAddr])); 70 | } 71 | else if(m_endian == MEM_BIG_ENDIAN) 72 | { 73 | return LH_BE(*((u16*) &m_pData[iAddr - m_iBaseAddr])); 74 | } 75 | else 76 | { 77 | COutput::Printf(LEVEL_DEBUG, "Invalid endian format\n"); 78 | } 79 | } 80 | else 81 | { 82 | COutput::Printf(LEVEL_DEBUG, "Invalid memory address 0x%08X\n", iAddr); 83 | } 84 | 85 | return 0; 86 | } 87 | 88 | u32 CVirtualMem::GetU32(u32 iAddr_2) 89 | { 90 | s32 iAddr = iAddr_2; 91 | 92 | if(CHECK_ADDR(iAddr, 4)) 93 | { 94 | if(m_endian == MEM_LITTLE_ENDIAN) 95 | { 96 | return LW_LE(*((u32*) &m_pData[iAddr - m_iBaseAddr])); 97 | } 98 | else if(m_endian == MEM_BIG_ENDIAN) 99 | { 100 | return LW_BE(*((u32*) &m_pData[iAddr - m_iBaseAddr])); 101 | } 102 | else 103 | { 104 | COutput::Printf(LEVEL_DEBUG, "Invalid endian format\n"); 105 | } 106 | } 107 | else 108 | { 109 | COutput::Printf(LEVEL_DEBUG, "Invalid memory address 0x%08X\n", iAddr); 110 | } 111 | 112 | return 0; 113 | } 114 | 115 | s8 CVirtualMem::GetS8(u32 iAddr) 116 | { 117 | if(CHECK_ADDR(iAddr, 1)) 118 | { 119 | return m_pData[iAddr - m_iBaseAddr]; 120 | } 121 | 122 | COutput::Printf(LEVEL_DEBUG, "Invalid memory address 0x%08X\n", iAddr); 123 | 124 | return 0; 125 | } 126 | 127 | s16 CVirtualMem::GetS16(u32 iAddr) 128 | { 129 | if(CHECK_ADDR(iAddr, 2)) 130 | { 131 | if(m_endian == MEM_LITTLE_ENDIAN) 132 | { 133 | return LH_LE(*((u16*) &m_pData[iAddr - m_iBaseAddr])); 134 | } 135 | else if(m_endian == MEM_BIG_ENDIAN) 136 | { 137 | return LH_BE(*((u16*) &m_pData[iAddr - m_iBaseAddr])); 138 | } 139 | else 140 | { 141 | COutput::Printf(LEVEL_DEBUG, "Invalid endian format\n"); 142 | } 143 | } 144 | else 145 | { 146 | COutput::Printf(LEVEL_DEBUG, "Invalid memory address 0x%08X\n", iAddr); 147 | } 148 | 149 | 150 | return 0; 151 | } 152 | 153 | s32 CVirtualMem::GetS32(u32 iAddr) 154 | { 155 | if(CHECK_ADDR(iAddr, 4)) 156 | { 157 | if(m_endian == MEM_LITTLE_ENDIAN) 158 | { 159 | return LW_LE(*((u32*) &m_pData[iAddr - m_iBaseAddr])); 160 | } 161 | else if(m_endian == MEM_BIG_ENDIAN) 162 | { 163 | return LW_BE(*((u32*) &m_pData[iAddr - m_iBaseAddr])); 164 | } 165 | else 166 | { 167 | COutput::Printf(LEVEL_DEBUG, "Invalid endian format\n"); 168 | } 169 | } 170 | else 171 | { 172 | COutput::Printf(LEVEL_DEBUG, "Invalid memory address 0x%08X\n", iAddr); 173 | } 174 | 175 | return 0; 176 | } 177 | 178 | void *CVirtualMem::GetPtr(u32 iAddr) 179 | { 180 | if(CHECK_ADDR(iAddr, 1)) 181 | { 182 | return &m_pData[iAddr - m_iBaseAddr]; 183 | } 184 | else 185 | { 186 | COutput::Printf(LEVEL_DEBUG, "Ptr out of region 0x%08X\n", iAddr); 187 | } 188 | 189 | return NULL; 190 | } 191 | 192 | /* Get the amount of data available from this address */ 193 | u32 CVirtualMem::GetSize(u32 iAddr) 194 | { 195 | u32 iSizeLeft = 0; 196 | 197 | /* Check we have at least 1 byte left */ 198 | if(CHECK_ADDR(iAddr, 1)) 199 | { 200 | iSizeLeft = m_iSize - (iAddr - m_iBaseAddr); 201 | } 202 | 203 | return iSizeLeft; 204 | } 205 | 206 | u32 CVirtualMem::Copy(void *pDest, u32 iAddr, u32 iSize) 207 | { 208 | u32 iCopySize; 209 | void *ptr; 210 | 211 | iCopySize = GetSize(iAddr); 212 | iCopySize = iCopySize > iSize ? iSize : iCopySize; 213 | 214 | if(iCopySize > 0) 215 | { 216 | ptr = GetPtr(iAddr); 217 | memcpy(pDest, ptr, iCopySize); 218 | } 219 | 220 | return iCopySize; 221 | } 222 | -------------------------------------------------------------------------------- /VirtualMem.h: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | * PRXTool : Utility for PSP executables. 3 | * (c) TyRaNiD 2k5 4 | * 5 | * VirtualMem.h - Definition of a class to create a virtual 6 | * memory space. 7 | ***************************************************************/ 8 | 9 | #ifndef __VIRTUALMEM_H__ 10 | #define __VIRTUALMEM_H__ 11 | 12 | #include "types.h" 13 | 14 | enum MemEndian 15 | { 16 | MEM_LITTLE_ENDIAN = 0, 17 | MEM_BIG_ENDIAN = 1 18 | }; 19 | 20 | class CVirtualMem 21 | { 22 | u8 *m_pData; 23 | u32 m_iSize; 24 | s32 m_iBaseAddr; 25 | MemEndian m_endian; 26 | public: 27 | CVirtualMem(); 28 | CVirtualMem(u8* pData, u32 iSize, u32 iBaseAddr, MemEndian endian); 29 | ~CVirtualMem(); 30 | 31 | u8 GetU8(u32 iAddr); 32 | u16 GetU16(u32 iAddr); 33 | u32 GetU32(u32 iAddr); 34 | s8 GetS8(u32 iAddr); 35 | s16 GetS16(u32 iAddr); 36 | s32 GetS32(u32 iAddr); 37 | void *GetPtr(u32 iAddr); 38 | u32 GetSize(u32 iAddr); 39 | u32 Copy(void *pDest, u32 iAddr, u32 iSize); 40 | }; 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /aclocal/ax_create_stdint_h.m4: -------------------------------------------------------------------------------- 1 | dnl @synopsis AX_CREATE_STDINT_H [( HEADER-TO-GENERATE [, HEDERS-TO-CHECK])] 2 | dnl 3 | dnl the "ISO C9X: 7.18 Integer types " section requires the 4 | dnl existence of an include file that defines a set of 5 | dnl typedefs, especially uint8_t,int32_t,uintptr_t. Many older 6 | dnl installations will not provide this file, but some will have the 7 | dnl very same definitions in . In other enviroments we can 8 | dnl use the inet-types in which would define the typedefs 9 | dnl int8_t and u_int8_t respectivly. 10 | dnl 11 | dnl This macros will create a local "_stdint.h" or the headerfile given 12 | dnl as an argument. In many cases that file will just "#include 13 | dnl " or "#include ", while in other environments 14 | dnl it will provide the set of basic 'stdint's definitions/typedefs: 15 | dnl 16 | dnl int8_t,uint8_t,int16_t,uint16_t,int32_t,uint32_t,intptr_t,uintptr_t 17 | dnl int_least32_t.. int_fast32_t.. intmax_t 18 | dnl 19 | dnl which may or may not rely on the definitions of other files, or 20 | dnl using the AC_CHECK_SIZEOF macro to determine the actual sizeof each 21 | dnl type. 22 | dnl 23 | dnl if your header files require the stdint-types you will want to 24 | dnl create an installable file mylib-int.h that all your other 25 | dnl installable header may include. So if you have a library package 26 | dnl named "mylib", just use 27 | dnl 28 | dnl AX_CREATE_STDINT_H(mylib-int.h) 29 | dnl 30 | dnl in configure.ac and go to install that very header file in 31 | dnl Makefile.am along with the other headers (mylib.h) - and the 32 | dnl mylib-specific headers can simply use "#include " to 33 | dnl obtain the stdint-types. 34 | dnl 35 | dnl Remember, if the system already had a valid , the 36 | dnl generated file will include it directly. No need for fuzzy 37 | dnl HAVE_STDINT_H things... 38 | dnl 39 | dnl @category C 40 | dnl @author Guido Draheim 41 | dnl @version 2003-12-07 42 | dnl @license GPLWithACException 43 | 44 | AC_DEFUN([AX_CHECK_DATA_MODEL],[ 45 | AC_CHECK_SIZEOF(char) 46 | AC_CHECK_SIZEOF(short) 47 | AC_CHECK_SIZEOF(int) 48 | AC_CHECK_SIZEOF(long) 49 | AC_CHECK_SIZEOF(void*) 50 | ac_cv_char_data_model="" 51 | ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_char" 52 | ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_short" 53 | ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_int" 54 | ac_cv_long_data_model="" 55 | ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_int" 56 | ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_long" 57 | ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_voidp" 58 | AC_MSG_CHECKING([data model]) 59 | case "$ac_cv_char_data_model/$ac_cv_long_data_model" in 60 | 122/242) ac_cv_data_model="IP16" ; n="standard 16bit machine" ;; 61 | 122/244) ac_cv_data_model="LP32" ; n="standard 32bit machine" ;; 62 | 122/*) ac_cv_data_model="i16" ; n="unusual int16 model" ;; 63 | 124/444) ac_cv_data_model="ILP32" ; n="standard 32bit unixish" ;; 64 | 124/488) ac_cv_data_model="LP64" ; n="standard 64bit unixish" ;; 65 | 124/448) ac_cv_data_model="LLP64" ; n="unusual 64bit unixish" ;; 66 | 124/*) ac_cv_data_model="i32" ; n="unusual int32 model" ;; 67 | 128/888) ac_cv_data_model="ILP64" ; n="unusual 64bit numeric" ;; 68 | 128/*) ac_cv_data_model="i64" ; n="unusual int64 model" ;; 69 | 222/*2) ac_cv_data_model="DSP16" ; n="strict 16bit dsptype" ;; 70 | 333/*3) ac_cv_data_model="DSP24" ; n="strict 24bit dsptype" ;; 71 | 444/*4) ac_cv_data_model="DSP32" ; n="strict 32bit dsptype" ;; 72 | 666/*6) ac_cv_data_model="DSP48" ; n="strict 48bit dsptype" ;; 73 | 888/*8) ac_cv_data_model="DSP64" ; n="strict 64bit dsptype" ;; 74 | 222/*|333/*|444/*|666/*|888/*) : 75 | ac_cv_data_model="iDSP" ; n="unusual dsptype" ;; 76 | *) ac_cv_data_model="none" ; n="very unusual model" ;; 77 | esac 78 | AC_MSG_RESULT([$ac_cv_data_model ($ac_cv_long_data_model, $n)]) 79 | ]) 80 | 81 | dnl AX_CHECK_HEADER_STDINT_X([HEADERLIST][,ACTION-IF]) 82 | AC_DEFUN([AX_CHECK_HEADER_STDINT_X],[ 83 | AC_CACHE_CHECK([for stdint uintptr_t], [ac_cv_header_stdint_x],[ 84 | ac_cv_header_stdint_x="" # the 1997 typedefs (inttypes.h) 85 | AC_MSG_RESULT([(..)]) 86 | for i in m4_ifval([$1],[$1],[stdint.h inttypes.h sys/inttypes.h]) ; do 87 | unset ac_cv_type_uintptr_t 88 | unset ac_cv_type_uint64_t 89 | AC_CHECK_TYPE(uintptr_t,[ac_cv_header_stdint_x=$i],continue,[#include <$i>]) 90 | AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>]) 91 | m4_ifvaln([$1],[$1]) break 92 | done 93 | AC_MSG_CHECKING([for stdint uintptr_t]) 94 | ]) 95 | ]) 96 | 97 | AC_DEFUN([AX_CHECK_HEADER_STDINT_O],[ 98 | AC_CACHE_CHECK([for stdint uint32_t], [ac_cv_header_stdint_o],[ 99 | ac_cv_header_stdint_o="" # the 1995 typedefs (sys/inttypes.h) 100 | AC_MSG_RESULT([(..)]) 101 | for i in m4_ifval([$1],[$1],[inttypes.h sys/inttypes.h stdint.h]) ; do 102 | unset ac_cv_type_uint32_t 103 | unset ac_cv_type_uint64_t 104 | AC_CHECK_TYPE(uint32_t,[ac_cv_header_stdint_o=$i],continue,[#include <$i>]) 105 | AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>]) 106 | m4_ifvaln([$1],[$1]) break 107 | break; 108 | done 109 | AC_MSG_CHECKING([for stdint uint32_t]) 110 | ]) 111 | ]) 112 | 113 | AC_DEFUN([AX_CHECK_HEADER_STDINT_U],[ 114 | AC_CACHE_CHECK([for stdint u_int32_t], [ac_cv_header_stdint_u],[ 115 | ac_cv_header_stdint_u="" # the BSD typedefs (sys/types.h) 116 | AC_MSG_RESULT([(..)]) 117 | for i in m4_ifval([$1],[$1],[sys/types.h inttypes.h sys/inttypes.h]) ; do 118 | unset ac_cv_type_u_int32_t 119 | unset ac_cv_type_u_int64_t 120 | AC_CHECK_TYPE(u_int32_t,[ac_cv_header_stdint_u=$i],continue,[#include <$i>]) 121 | AC_CHECK_TYPE(u_int64_t,[and64="/u_int64_t"],[and64=""],[#include<$i>]) 122 | m4_ifvaln([$1],[$1]) break 123 | break; 124 | done 125 | AC_MSG_CHECKING([for stdint u_int32_t]) 126 | ]) 127 | ]) 128 | 129 | AC_DEFUN([AX_CREATE_STDINT_H], 130 | [# ------ AX CREATE STDINT H ------------------------------------- 131 | AC_MSG_CHECKING([for stdint types]) 132 | ac_stdint_h=`echo ifelse($1, , _stdint.h, $1)` 133 | # try to shortcircuit - if the default include path of the compiler 134 | # can find a "stdint.h" header then we assume that all compilers can. 135 | AC_CACHE_VAL([ac_cv_header_stdint_t],[ 136 | old_CXXFLAGS="$CXXFLAGS" ; CXXFLAGS="" 137 | old_CPPFLAGS="$CPPFLAGS" ; CPPFLAGS="" 138 | old_CFLAGS="$CFLAGS" ; CFLAGS="" 139 | AC_TRY_COMPILE([#include ],[int_least32_t v = 0;], 140 | [ac_cv_stdint_result="(assuming C99 compatible system)" 141 | ac_cv_header_stdint_t="stdint.h"; ], 142 | [ac_cv_header_stdint_t=""]) 143 | CXXFLAGS="$old_CXXFLAGS" 144 | CPPFLAGS="$old_CPPFLAGS" 145 | CFLAGS="$old_CFLAGS" ]) 146 | 147 | v="... $ac_cv_header_stdint_h" 148 | if test "$ac_stdint_h" = "stdint.h" ; then 149 | AC_MSG_RESULT([(are you sure you want them in ./stdint.h?)]) 150 | elif test "$ac_stdint_h" = "inttypes.h" ; then 151 | AC_MSG_RESULT([(are you sure you want them in ./inttypes.h?)]) 152 | elif test "_$ac_cv_header_stdint_t" = "_" ; then 153 | AC_MSG_RESULT([(putting them into $ac_stdint_h)$v]) 154 | else 155 | ac_cv_header_stdint="$ac_cv_header_stdint_t" 156 | AC_MSG_RESULT([$ac_cv_header_stdint (shortcircuit)]) 157 | fi 158 | 159 | if test "_$ac_cv_header_stdint_t" = "_" ; then # can not shortcircuit.. 160 | 161 | dnl .....intro message done, now do a few system checks..... 162 | dnl btw, all old CHECK_TYPE macros do automatically "DEFINE" a type, 163 | dnl therefore we use the autoconf implementation detail CHECK_TYPE_NEW 164 | dnl instead that is triggered with 3 or more arguments (see types.m4) 165 | 166 | inttype_headers=`echo $2 | sed -e 's/,/ /g'` 167 | 168 | ac_cv_stdint_result="(no helpful system typedefs seen)" 169 | AX_CHECK_HEADER_STDINT_X(dnl 170 | stdint.h inttypes.h sys/inttypes.h $inttype_headers, 171 | ac_cv_stdint_result="(seen uintptr_t$and64 in $i)") 172 | 173 | if test "_$ac_cv_header_stdint_x" = "_" ; then 174 | AX_CHECK_HEADER_STDINT_O(dnl, 175 | inttypes.h sys/inttypes.h stdint.h $inttype_headers, 176 | ac_cv_stdint_result="(seen uint32_t$and64 in $i)") 177 | fi 178 | 179 | if test "_$ac_cv_header_stdint_x" = "_" ; then 180 | if test "_$ac_cv_header_stdint_o" = "_" ; then 181 | AX_CHECK_HEADER_STDINT_U(dnl, 182 | sys/types.h inttypes.h sys/inttypes.h $inttype_headers, 183 | ac_cv_stdint_result="(seen u_int32_t$and64 in $i)") 184 | fi fi 185 | 186 | dnl if there was no good C99 header file, do some typedef checks... 187 | if test "_$ac_cv_header_stdint_x" = "_" ; then 188 | AC_MSG_CHECKING([for stdint datatype model]) 189 | AC_MSG_RESULT([(..)]) 190 | AX_CHECK_DATA_MODEL 191 | fi 192 | 193 | if test "_$ac_cv_header_stdint_x" != "_" ; then 194 | ac_cv_header_stdint="$ac_cv_header_stdint_x" 195 | elif test "_$ac_cv_header_stdint_o" != "_" ; then 196 | ac_cv_header_stdint="$ac_cv_header_stdint_o" 197 | elif test "_$ac_cv_header_stdint_u" != "_" ; then 198 | ac_cv_header_stdint="$ac_cv_header_stdint_u" 199 | else 200 | ac_cv_header_stdint="stddef.h" 201 | fi 202 | 203 | AC_MSG_CHECKING([for extra inttypes in chosen header]) 204 | AC_MSG_RESULT([($ac_cv_header_stdint)]) 205 | dnl see if int_least and int_fast types are present in _this_ header. 206 | unset ac_cv_type_int_least32_t 207 | unset ac_cv_type_int_fast32_t 208 | AC_CHECK_TYPE(int_least32_t,,,[#include <$ac_cv_header_stdint>]) 209 | AC_CHECK_TYPE(int_fast32_t,,,[#include<$ac_cv_header_stdint>]) 210 | AC_CHECK_TYPE(intmax_t,,,[#include <$ac_cv_header_stdint>]) 211 | 212 | fi # shortcircut to system "stdint.h" 213 | # ------------------ PREPARE VARIABLES ------------------------------ 214 | if test "$GCC" = "yes" ; then 215 | ac_cv_stdint_message="using gnu compiler "`$CC --version | head -1` 216 | else 217 | ac_cv_stdint_message="using $CC" 218 | fi 219 | 220 | AC_MSG_RESULT([make use of $ac_cv_header_stdint in $ac_stdint_h dnl 221 | $ac_cv_stdint_result]) 222 | 223 | dnl ----------------------------------------------------------------- 224 | # ----------------- DONE inttypes.h checks START header ------------- 225 | AC_CONFIG_COMMANDS([$ac_stdint_h],[ 226 | AC_MSG_NOTICE(creating $ac_stdint_h : $_ac_stdint_h) 227 | ac_stdint=$tmp/_stdint.h 228 | 229 | echo "#ifndef" $_ac_stdint_h >$ac_stdint 230 | echo "#define" $_ac_stdint_h "1" >>$ac_stdint 231 | echo "#ifndef" _GENERATED_STDINT_H >>$ac_stdint 232 | echo "#define" _GENERATED_STDINT_H '"'$PACKAGE $VERSION'"' >>$ac_stdint 233 | echo "/* generated $ac_cv_stdint_message */" >>$ac_stdint 234 | if test "_$ac_cv_header_stdint_t" != "_" ; then 235 | echo "#define _STDINT_HAVE_STDINT_H" "1" >>$ac_stdint 236 | echo "#include " >>$ac_stdint 237 | echo "#endif" >>$ac_stdint 238 | echo "#endif" >>$ac_stdint 239 | else 240 | 241 | cat >>$ac_stdint < 247 | #else 248 | #include 249 | 250 | /* .................... configured part ............................ */ 251 | 252 | STDINT_EOF 253 | 254 | echo "/* whether we have a C99 compatible stdint header file */" >>$ac_stdint 255 | if test "_$ac_cv_header_stdint_x" != "_" ; then 256 | ac_header="$ac_cv_header_stdint_x" 257 | echo "#define _STDINT_HEADER_INTPTR" '"'"$ac_header"'"' >>$ac_stdint 258 | else 259 | echo "/* #undef _STDINT_HEADER_INTPTR */" >>$ac_stdint 260 | fi 261 | 262 | echo "/* whether we have a C96 compatible inttypes header file */" >>$ac_stdint 263 | if test "_$ac_cv_header_stdint_o" != "_" ; then 264 | ac_header="$ac_cv_header_stdint_o" 265 | echo "#define _STDINT_HEADER_UINT32" '"'"$ac_header"'"' >>$ac_stdint 266 | else 267 | echo "/* #undef _STDINT_HEADER_UINT32 */" >>$ac_stdint 268 | fi 269 | 270 | echo "/* whether we have a BSD compatible inet types header */" >>$ac_stdint 271 | if test "_$ac_cv_header_stdint_u" != "_" ; then 272 | ac_header="$ac_cv_header_stdint_u" 273 | echo "#define _STDINT_HEADER_U_INT32" '"'"$ac_header"'"' >>$ac_stdint 274 | else 275 | echo "/* #undef _STDINT_HEADER_U_INT32 */" >>$ac_stdint 276 | fi 277 | 278 | echo "" >>$ac_stdint 279 | 280 | if test "_$ac_header" != "_" ; then if test "$ac_header" != "stddef.h" ; then 281 | echo "#include <$ac_header>" >>$ac_stdint 282 | echo "" >>$ac_stdint 283 | fi fi 284 | 285 | echo "/* which 64bit typedef has been found */" >>$ac_stdint 286 | if test "$ac_cv_type_uint64_t" = "yes" ; then 287 | echo "#define _STDINT_HAVE_UINT64_T" "1" >>$ac_stdint 288 | else 289 | echo "/* #undef _STDINT_HAVE_UINT64_T */" >>$ac_stdint 290 | fi 291 | if test "$ac_cv_type_u_int64_t" = "yes" ; then 292 | echo "#define _STDINT_HAVE_U_INT64_T" "1" >>$ac_stdint 293 | else 294 | echo "/* #undef _STDINT_HAVE_U_INT64_T */" >>$ac_stdint 295 | fi 296 | echo "" >>$ac_stdint 297 | 298 | echo "/* which type model has been detected */" >>$ac_stdint 299 | if test "_$ac_cv_char_data_model" != "_" ; then 300 | echo "#define _STDINT_CHAR_MODEL" "$ac_cv_char_data_model" >>$ac_stdint 301 | echo "#define _STDINT_LONG_MODEL" "$ac_cv_long_data_model" >>$ac_stdint 302 | else 303 | echo "/* #undef _STDINT_CHAR_MODEL // skipped */" >>$ac_stdint 304 | echo "/* #undef _STDINT_LONG_MODEL // skipped */" >>$ac_stdint 305 | fi 306 | echo "" >>$ac_stdint 307 | 308 | echo "/* whether int_least types were detected */" >>$ac_stdint 309 | if test "$ac_cv_type_int_least32_t" = "yes"; then 310 | echo "#define _STDINT_HAVE_INT_LEAST32_T" "1" >>$ac_stdint 311 | else 312 | echo "/* #undef _STDINT_HAVE_INT_LEAST32_T */" >>$ac_stdint 313 | fi 314 | echo "/* whether int_fast types were detected */" >>$ac_stdint 315 | if test "$ac_cv_type_int_fast32_t" = "yes"; then 316 | echo "#define _STDINT_HAVE_INT_FAST32_T" "1" >>$ac_stdint 317 | else 318 | echo "/* #undef _STDINT_HAVE_INT_FAST32_T */" >>$ac_stdint 319 | fi 320 | echo "/* whether intmax_t type was detected */" >>$ac_stdint 321 | if test "$ac_cv_type_intmax_t" = "yes"; then 322 | echo "#define _STDINT_HAVE_INTMAX_T" "1" >>$ac_stdint 323 | else 324 | echo "/* #undef _STDINT_HAVE_INTMAX_T */" >>$ac_stdint 325 | fi 326 | echo "" >>$ac_stdint 327 | 328 | cat >>$ac_stdint <= 199901L 385 | #define _HAVE_UINT64_T 386 | #define _HAVE_LONGLONG_UINT64_T 387 | typedef long long int64_t; 388 | typedef unsigned long long uint64_t; 389 | 390 | #elif !defined __STRICT_ANSI__ 391 | #if defined _MSC_VER || defined __WATCOMC__ || defined __BORLANDC__ 392 | #define _HAVE_UINT64_T 393 | typedef __int64 int64_t; 394 | typedef unsigned __int64 uint64_t; 395 | 396 | #elif defined __GNUC__ || defined __MWERKS__ || defined __ELF__ 397 | /* note: all ELF-systems seem to have loff-support which needs 64-bit */ 398 | #if !defined _NO_LONGLONG 399 | #define _HAVE_UINT64_T 400 | #define _HAVE_LONGLONG_UINT64_T 401 | typedef long long int64_t; 402 | typedef unsigned long long uint64_t; 403 | #endif 404 | 405 | #elif defined __alpha || (defined __mips && defined _ABIN32) 406 | #if !defined _NO_LONGLONG 407 | typedef long int64_t; 408 | typedef unsigned long uint64_t; 409 | #endif 410 | /* compiler/cpu type to define int64_t */ 411 | #endif 412 | #endif 413 | #endif 414 | 415 | #if defined _STDINT_HAVE_U_INT_TYPES 416 | /* int8_t int16_t int32_t defined by inet code, redeclare the u_intXX types */ 417 | typedef u_int8_t uint8_t; 418 | typedef u_int16_t uint16_t; 419 | typedef u_int32_t uint32_t; 420 | 421 | /* glibc compatibility */ 422 | #ifndef __int8_t_defined 423 | #define __int8_t_defined 424 | #endif 425 | #endif 426 | 427 | #ifdef _STDINT_NEED_INT_MODEL_T 428 | /* we must guess all the basic types. Apart from byte-adressable system, */ 429 | /* there a few 32-bit-only dsp-systems that we guard with BYTE_MODEL 8-} */ 430 | /* (btw, those nibble-addressable systems are way off, or so we assume) */ 431 | 432 | dnl /* have a look at "64bit and data size neutrality" at */ 433 | dnl /* http://unix.org/version2/whatsnew/login_64bit.html */ 434 | dnl /* (the shorthand "ILP" types always have a "P" part) */ 435 | 436 | #if defined _STDINT_BYTE_MODEL 437 | #if _STDINT_LONG_MODEL+0 == 242 438 | /* 2:4:2 = IP16 = a normal 16-bit system */ 439 | typedef unsigned char uint8_t; 440 | typedef unsigned short uint16_t; 441 | typedef unsigned long uint32_t; 442 | #ifndef __int8_t_defined 443 | #define __int8_t_defined 444 | typedef char int8_t; 445 | typedef short int16_t; 446 | typedef long int32_t; 447 | #endif 448 | #elif _STDINT_LONG_MODEL+0 == 244 || _STDINT_LONG_MODEL == 444 449 | /* 2:4:4 = LP32 = a 32-bit system derived from a 16-bit */ 450 | /* 4:4:4 = ILP32 = a normal 32-bit system */ 451 | typedef unsigned char uint8_t; 452 | typedef unsigned short uint16_t; 453 | typedef unsigned int uint32_t; 454 | #ifndef __int8_t_defined 455 | #define __int8_t_defined 456 | typedef char int8_t; 457 | typedef short int16_t; 458 | typedef int int32_t; 459 | #endif 460 | #elif _STDINT_LONG_MODEL+0 == 484 || _STDINT_LONG_MODEL+0 == 488 461 | /* 4:8:4 = IP32 = a 32-bit system prepared for 64-bit */ 462 | /* 4:8:8 = LP64 = a normal 64-bit system */ 463 | typedef unsigned char uint8_t; 464 | typedef unsigned short uint16_t; 465 | typedef unsigned int uint32_t; 466 | #ifndef __int8_t_defined 467 | #define __int8_t_defined 468 | typedef char int8_t; 469 | typedef short int16_t; 470 | typedef int int32_t; 471 | #endif 472 | /* this system has a "long" of 64bit */ 473 | #ifndef _HAVE_UINT64_T 474 | #define _HAVE_UINT64_T 475 | typedef unsigned long uint64_t; 476 | typedef long int64_t; 477 | #endif 478 | #elif _STDINT_LONG_MODEL+0 == 448 479 | /* LLP64 a 64-bit system derived from a 32-bit system */ 480 | typedef unsigned char uint8_t; 481 | typedef unsigned short uint16_t; 482 | typedef unsigned int uint32_t; 483 | #ifndef __int8_t_defined 484 | #define __int8_t_defined 485 | typedef char int8_t; 486 | typedef short int16_t; 487 | typedef int int32_t; 488 | #endif 489 | /* assuming the system has a "long long" */ 490 | #ifndef _HAVE_UINT64_T 491 | #define _HAVE_UINT64_T 492 | #define _HAVE_LONGLONG_UINT64_T 493 | typedef unsigned long long uint64_t; 494 | typedef long long int64_t; 495 | #endif 496 | #else 497 | #define _STDINT_NO_INT32_T 498 | #endif 499 | #else 500 | #define _STDINT_NO_INT8_T 501 | #define _STDINT_NO_INT32_T 502 | #endif 503 | #endif 504 | 505 | /* 506 | * quote from SunOS-5.8 sys/inttypes.h: 507 | * Use at your own risk. As of February 1996, the committee is squarely 508 | * behind the fixed sized types; the "least" and "fast" types are still being 509 | * discussed. The probability that the "fast" types may be removed before 510 | * the standard is finalized is high enough that they are not currently 511 | * implemented. 512 | */ 513 | 514 | #if defined _STDINT_NEED_INT_LEAST_T 515 | typedef int8_t int_least8_t; 516 | typedef int16_t int_least16_t; 517 | typedef int32_t int_least32_t; 518 | #ifdef _HAVE_UINT64_T 519 | typedef int64_t int_least64_t; 520 | #endif 521 | 522 | typedef uint8_t uint_least8_t; 523 | typedef uint16_t uint_least16_t; 524 | typedef uint32_t uint_least32_t; 525 | #ifdef _HAVE_UINT64_T 526 | typedef uint64_t uint_least64_t; 527 | #endif 528 | /* least types */ 529 | #endif 530 | 531 | #if defined _STDINT_NEED_INT_FAST_T 532 | typedef int8_t int_fast8_t; 533 | typedef int int_fast16_t; 534 | typedef int32_t int_fast32_t; 535 | #ifdef _HAVE_UINT64_T 536 | typedef int64_t int_fast64_t; 537 | #endif 538 | 539 | typedef uint8_t uint_fast8_t; 540 | typedef unsigned uint_fast16_t; 541 | typedef uint32_t uint_fast32_t; 542 | #ifdef _HAVE_UINT64_T 543 | typedef uint64_t uint_fast64_t; 544 | #endif 545 | /* fast types */ 546 | #endif 547 | 548 | #ifdef _STDINT_NEED_INTMAX_T 549 | #ifdef _HAVE_UINT64_T 550 | typedef int64_t intmax_t; 551 | typedef uint64_t uintmax_t; 552 | #else 553 | typedef long intmax_t; 554 | typedef unsigned long uintmax_t; 555 | #endif 556 | #endif 557 | 558 | #ifdef _STDINT_NEED_INTPTR_T 559 | #ifndef __intptr_t_defined 560 | #define __intptr_t_defined 561 | /* we encourage using "long" to store pointer values, never use "int" ! */ 562 | #if _STDINT_LONG_MODEL+0 == 242 || _STDINT_LONG_MODEL+0 == 484 563 | typedef unsinged int uintptr_t; 564 | typedef int intptr_t; 565 | #elif _STDINT_LONG_MODEL+0 == 244 || _STDINT_LONG_MODEL+0 == 444 566 | typedef unsigned long uintptr_t; 567 | typedef long intptr_t; 568 | #elif _STDINT_LONG_MODEL+0 == 448 && defined _HAVE_UINT64_T 569 | typedef uint64_t uintptr_t; 570 | typedef int64_t intptr_t; 571 | #else /* matches typical system types ILP32 and LP64 - but not IP16 or LLP64 */ 572 | typedef unsigned long uintptr_t; 573 | typedef long intptr_t; 574 | #endif 575 | #endif 576 | #endif 577 | 578 | /* The ISO C99 standard specifies that in C++ implementations these 579 | should only be defined if explicitly requested. */ 580 | #if !defined __cplusplus || defined __STDC_CONSTANT_MACROS 581 | #ifndef UINT32_C 582 | 583 | /* Signed. */ 584 | # define INT8_C(c) c 585 | # define INT16_C(c) c 586 | # define INT32_C(c) c 587 | # ifdef _HAVE_LONGLONG_UINT64_T 588 | # define INT64_C(c) c ## L 589 | # else 590 | # define INT64_C(c) c ## LL 591 | # endif 592 | 593 | /* Unsigned. */ 594 | # define UINT8_C(c) c ## U 595 | # define UINT16_C(c) c ## U 596 | # define UINT32_C(c) c ## U 597 | # ifdef _HAVE_LONGLONG_UINT64_T 598 | # define UINT64_C(c) c ## UL 599 | # else 600 | # define UINT64_C(c) c ## ULL 601 | # endif 602 | 603 | /* Maximal type. */ 604 | # ifdef _HAVE_LONGLONG_UINT64_T 605 | # define INTMAX_C(c) c ## L 606 | # define UINTMAX_C(c) c ## UL 607 | # else 608 | # define INTMAX_C(c) c ## LL 609 | # define UINTMAX_C(c) c ## ULL 610 | # endif 611 | 612 | /* literalnumbers */ 613 | #endif 614 | #endif 615 | 616 | /* These limits are merily those of a two complement byte-oriented system */ 617 | 618 | /* Minimum of signed integral types. */ 619 | # define INT8_MIN (-128) 620 | # define INT16_MIN (-32767-1) 621 | # define INT32_MIN (-2147483647-1) 622 | # define INT64_MIN (-__INT64_C(9223372036854775807)-1) 623 | /* Maximum of signed integral types. */ 624 | # define INT8_MAX (127) 625 | # define INT16_MAX (32767) 626 | # define INT32_MAX (2147483647) 627 | # define INT64_MAX (__INT64_C(9223372036854775807)) 628 | 629 | /* Maximum of unsigned integral types. */ 630 | # define UINT8_MAX (255) 631 | # define UINT16_MAX (65535) 632 | # define UINT32_MAX (4294967295U) 633 | # define UINT64_MAX (__UINT64_C(18446744073709551615)) 634 | 635 | /* Minimum of signed integral types having a minimum size. */ 636 | # define INT_LEAST8_MIN INT8_MIN 637 | # define INT_LEAST16_MIN INT16_MIN 638 | # define INT_LEAST32_MIN INT32_MIN 639 | # define INT_LEAST64_MIN INT64_MIN 640 | /* Maximum of signed integral types having a minimum size. */ 641 | # define INT_LEAST8_MAX INT8_MAX 642 | # define INT_LEAST16_MAX INT16_MAX 643 | # define INT_LEAST32_MAX INT32_MAX 644 | # define INT_LEAST64_MAX INT64_MAX 645 | 646 | /* Maximum of unsigned integral types having a minimum size. */ 647 | # define UINT_LEAST8_MAX UINT8_MAX 648 | # define UINT_LEAST16_MAX UINT16_MAX 649 | # define UINT_LEAST32_MAX UINT32_MAX 650 | # define UINT_LEAST64_MAX UINT64_MAX 651 | 652 | /* shortcircuit*/ 653 | #endif 654 | /* once */ 655 | #endif 656 | #endif 657 | STDINT_EOF 658 | fi 659 | if cmp -s $ac_stdint_h $ac_stdint 2>/dev/null; then 660 | AC_MSG_NOTICE([$ac_stdint_h is unchanged]) 661 | else 662 | ac_dir=`AS_DIRNAME(["$ac_stdint_h"])` 663 | AS_MKDIR_P(["$ac_dir"]) 664 | rm -f $ac_stdint_h 665 | mv $ac_stdint $ac_stdint_h 666 | fi 667 | ],[# variables for create stdint.h replacement 668 | PACKAGE="$PACKAGE" 669 | VERSION="$VERSION" 670 | ac_stdint_h="$ac_stdint_h" 671 | _ac_stdint_h=AS_TR_CPP(_$PACKAGE-$ac_stdint_h) 672 | ac_cv_stdint_message="$ac_cv_stdint_message" 673 | ac_cv_header_stdint_t="$ac_cv_header_stdint_t" 674 | ac_cv_header_stdint_x="$ac_cv_header_stdint_x" 675 | ac_cv_header_stdint_o="$ac_cv_header_stdint_o" 676 | ac_cv_header_stdint_u="$ac_cv_header_stdint_u" 677 | ac_cv_type_uint64_t="$ac_cv_type_uint64_t" 678 | ac_cv_type_u_int64_t="$ac_cv_type_u_int64_t" 679 | ac_cv_char_data_model="$ac_cv_char_data_model" 680 | ac_cv_long_data_model="$ac_cv_long_data_model" 681 | ac_cv_type_int_least32_t="$ac_cv_type_int_least32_t" 682 | ac_cv_type_int_fast32_t="$ac_cv_type_int_fast32_t" 683 | ac_cv_type_intmax_t="$ac_cv_type_intmax_t" 684 | ]) 685 | ]) 686 | -------------------------------------------------------------------------------- /aclocal/version.m4: -------------------------------------------------------------------------------- 1 | AC_DEFUN([PRXTOOL_VERSIONING], 2 | m4_define([PRXTOOL_VERSION],[0.1.0])) 3 | 4 | AC_DEFUN(AC_PRXTOOL_VERSION, 5 | [ 6 | AC_REQUIRE([PRXTOOL_VERSIONING]) 7 | AC_BEFORE([$0], [AM_INIT_AUTOMAKE]) 8 | 9 | AC_MSG_CHECKING([for prxtool version]) 10 | AS_IF([test -r "${srcdir}/aclocal/version.m4"], 11 | [], 12 | [AC_MSG_ERROR([Unable to find aclocal/version.m4])]) 13 | AC_MSG_RESULT([PRXTOOL_VERSION]) 14 | ]) 15 | -------------------------------------------------------------------------------- /bootstrap: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # helps bootstrapping, when checked out from CVS 4 | # requires GNU autoconf and GNU automake 5 | # 6 | # NOTE: Inspired by libtool's autogen script 7 | 8 | progname=`basename $0` 9 | top_srcdir=`dirname $0` 10 | 11 | verbose=""; 12 | quiet="false" 13 | mode="generate" 14 | 15 | usage() 16 | { 17 | echo 18 | echo "usage: ${progname} [-h|-q|-v|-c]" 19 | echo 20 | echo "options:" 21 | echo " -h .. display this message and exit"; 22 | echo " -q .. quiet, don't display directories"; 23 | echo " -v .. verbose, pass -v to automake when invoking automake" 24 | echo " -c .. clean, remove all aclocal/autoconf/automake generated files" 25 | echo 26 | exit 1; 27 | } 28 | 29 | if test ! -f $top_srcdir/aclocal/version.m4; then 30 | echo "${progname}:" 31 | echo " Installation problem: Can't find file aclocal/version.m4" 32 | exit 1; 33 | fi 34 | 35 | while test $# -gt 0; do 36 | case $1 in 37 | -h|--he|--hel|--help) 38 | usage ;; 39 | -q|--qu|--qui|--quie|--quiet) 40 | quiet="true"; 41 | shift;; 42 | -v|--ve|--ver|--verb|--verbo|--verbos|--verbose) 43 | verbose="-v"; 44 | shift;; 45 | -c|--cl|--cle|--clea|--clean) 46 | mode="clean"; 47 | shift;; 48 | -*) echo "unknown option $1" ; 49 | usage ;; 50 | *) echo "invalid parameter $1" ; 51 | usage ;; 52 | esac 53 | done 54 | 55 | case $mode in 56 | generate) 57 | 58 | case $top_srcdir in 59 | /* ) aclocal_dir=$top_srcdir 60 | ;; 61 | *) aclocal_dir=`pwd`/$top_srcdir 62 | ;; 63 | esac 64 | 65 | confs=`find . \( -name 'configure.in' -o -name 'configure.ac' \) -print` 66 | for i in $confs; do 67 | dir=`dirname $i`; 68 | configure=`basename $i`; 69 | ( test "$quiet" = "true" || echo "$dir"; 70 | cd $dir; 71 | pat="s,\$(TOPdir),${aclocal_dir},g" 72 | aclocal_args=`grep '^[ ]*ACLOCAL_AMFLAGS' Makefile.am | \ 73 | sed -e 's%.*ACLOCAL_AMFLAGS.*\=[ ]*%%g' -e $pat ` ; 74 | test "$verbose" = "-v" && echo "aclocal $aclocal_args" 75 | aclocal $aclocal_args; 76 | test -n "`grep CONFIG_HEADER ${configure}`" && autoheader \ 77 | && test "$verbose" = "-v" && echo "autoheader"; 78 | test -f Makefile.am && automake -a -c --foreign $verbose ; 79 | test "$verbose" = "-v" && echo "autoconf"; 80 | autoconf; 81 | test -f Makefile.am && test -n "`grep 'stamp-h\.in' Makefile.in`" \ 82 | && echo timestamp > stamp-h.in 83 | ) 84 | done 85 | ;; 86 | 87 | clean) 88 | test "$quiet" = "true" || echo "removing automake generated Makefile.in files" 89 | files=`find . -name 'Makefile.am' -print | sed -e 's%\.am%\.in%g'` ; 90 | for i in $files; do if test -f $i; then 91 | rm -f $i 92 | test "$verbose" = "-v" && echo "$i" 93 | fi; done 94 | 95 | test "$quiet" = "true" || echo "removing configure files" 96 | files=`find . -name 'configure' -print` ; 97 | test "$verbose" = "-v" && test -n "$files" && echo "$files" ; 98 | for i in $files; do if test -f $i; then 99 | rm -f $i config.guess config.sub depcomp install-sh mdate-sh missing \ 100 | mkinstalldirs texinfo.tex 101 | test "$verbose" = "-v" && echo "$i" 102 | fi; done 103 | 104 | test "$quiet" = "true" || echo "removing aclocal.m4 files" 105 | files=`find . -name 'aclocal.m4' -print` ; 106 | test "$verbose" = "-v" && test -n "$files" && echo "$files" ; 107 | for i in $files; do if test -f $i; then 108 | rm -f $i 109 | test "$verbose" = "-v" && echo "$i" 110 | fi; done 111 | 112 | find . -name '*~' -print | xargs rm -f 113 | find . -name '*.orig' -print | xargs rm -f 114 | find . -name '*.rej' -print | xargs rm -f 115 | find . -name 'config.status' -print | xargs rm -f 116 | find . -name 'config.log' -print | xargs rm -f 117 | find . -name 'config.cache' -print | xargs rm -f 118 | find . -name 'Makefile' -print | xargs rm -f 119 | find . -name '.deps' -print | xargs rm -rf 120 | find . -name '.libs' -print | xargs rm -rf 121 | find . -name 'stamp-h.in' | xargs rm -rf 122 | ;; 123 | esac 124 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ(2.59) 5 | AC_INIT([prxtool], [PRXTOOL_VERSION], []) 6 | AC_CONFIG_SRCDIR([main.C]) 7 | AC_CONFIG_HEADER([config.h]) 8 | AC_PRXTOOL_VERSION 9 | 10 | AM_INIT_AUTOMAKE([prxtool], [PRXTOOL_VERSION]) 11 | 12 | # Checks for programs. 13 | AC_PROG_CXX 14 | AC_PROG_CC 15 | 16 | # Checks for libraries. 17 | 18 | # Checks for header files. 19 | AC_HEADER_STDC 20 | AC_CHECK_HEADERS([stddef.h stdlib.h string.h unistd.h]) 21 | AX_CREATE_STDINT_H 22 | 23 | # Checks for typedefs, structures, and compiler characteristics. 24 | AC_HEADER_STDBOOL 25 | AC_C_CONST 26 | AC_C_INLINE 27 | AC_TYPE_SIZE_T 28 | AC_CHECK_TYPES([ptrdiff_t]) 29 | AC_C_BIGENDIAN 30 | 31 | # Checks for library functions. 32 | AC_CHECK_FUNCS([memset strchr strtoul]) 33 | 34 | AC_CONFIG_FILES([Makefile]) 35 | AC_OUTPUT 36 | -------------------------------------------------------------------------------- /disasm.C: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | * PRXTool : Utility for PSP executables. 3 | * (c) TyRaNiD 2k6 4 | * 5 | * disasm.C - Implementation of a MIPS disassembler 6 | ***************************************************************/ 7 | 8 | #include 9 | #include 10 | #include "disasm.h" 11 | 12 | #include 13 | 14 | static int g_hexints = 0; 15 | static int g_mregs = 0; 16 | static int g_symaddr = 0; 17 | static int g_macroon = 0; 18 | static int g_printreal = 0; 19 | static int g_printregs = 0; 20 | static int g_regmask = 0; 21 | static int g_printswap = 0; 22 | static int g_signedhex = 0; 23 | static int g_xmloutput = 0; 24 | static SymbolMap *g_syms = NULL; 25 | 26 | struct DisasmOpt 27 | { 28 | char opt; 29 | int *value; 30 | const char *name; 31 | }; 32 | 33 | struct DisasmOpt g_disopts[DISASM_OPT_MAX] = { 34 | { DISASM_OPT_HEXINTS, &g_hexints, "Hex Integers" }, 35 | { DISASM_OPT_MREGS, &g_mregs, "Mnemonic Registers" }, 36 | { DISASM_OPT_SYMADDR, &g_symaddr, "Symbol Address" }, 37 | { DISASM_OPT_MACRO, &g_macroon, "Macros" }, 38 | { DISASM_OPT_PRINTREAL, &g_printreal, "Print Real Address" }, 39 | { DISASM_OPT_PRINTREGS, &g_printregs, "Print Regs" }, 40 | { DISASM_OPT_PRINTSWAP, &g_printswap, "Print Swap" }, 41 | { DISASM_OPT_SIGNEDHEX, &g_signedhex, "Signed Hex" }, 42 | }; 43 | 44 | cs_mode disasm_mode = (cs_mode)(CS_MODE_ARM); 45 | 46 | void SetThumbMode(bool mode) 47 | { 48 | if(mode) 49 | { 50 | disasm_mode = (cs_mode)(CS_MODE_THUMB); 51 | } 52 | } 53 | 54 | SymbolType disasmResolveSymbol(unsigned int PC, char *name, int namelen) 55 | { 56 | SymbolEntry *s; 57 | SymbolType type = SYMBOL_NOSYM; 58 | 59 | if(g_syms) 60 | { 61 | s = (*g_syms)[PC]; 62 | if(s) 63 | { 64 | type = s->type; 65 | snprintf(name, namelen, "%s", s->name.c_str()); 66 | } 67 | } 68 | 69 | return type; 70 | } 71 | 72 | SymbolType disasmResolveRef(unsigned int PC, char *name, int namelen) 73 | { 74 | SymbolEntry *s; 75 | SymbolType type = SYMBOL_NOSYM; 76 | 77 | if(g_syms) 78 | { 79 | s = (*g_syms)[PC]; 80 | if((s) && (s->imported.size() > 0)) 81 | { 82 | unsigned int nid = 0; 83 | PspLibImport *pImp = s->imported[0]; 84 | 85 | for(int i = 0; i < pImp->f_count; i++) 86 | { 87 | if(strcmp(s->name.c_str(), pImp->funcs[i].name) == 0) 88 | { 89 | nid = pImp->funcs[i].nid; 90 | break; 91 | } 92 | } 93 | type = s->type; 94 | snprintf(name, namelen, "/%s/%s/nid:0x%08X", pImp->file, pImp->name, nid); 95 | } 96 | } 97 | 98 | return type; 99 | } 100 | 101 | SymbolEntry* disasmFindSymbol(unsigned int PC) 102 | { 103 | SymbolEntry *s = NULL; 104 | 105 | if(g_syms) 106 | { 107 | s = (*g_syms)[PC]; 108 | } 109 | 110 | return s; 111 | } 112 | 113 | int disasmIsBranch(unsigned int opcode, unsigned int *PC, unsigned int *dwTarget) 114 | { 115 | u32 old_PC = *PC; 116 | 117 | int type = 0; 118 | 119 | static csh handle; 120 | cs_err err = cs_open(CS_ARCH_ARM, disasm_mode, &handle); 121 | if (err) { 122 | (*PC) += 4; 123 | return 0; 124 | } 125 | 126 | cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); 127 | 128 | cs_insn *insn; 129 | size_t count = cs_disasm(handle, (unsigned char *)&opcode, 4, *PC, 0, &insn); 130 | size_t ori_count = count; 131 | if (count) { 132 | if (count == 1) { 133 | cs_insn *insn2; 134 | int count2 = cs_disasm(handle, (unsigned char *)&opcode, 2, *PC, 0, &insn2); 135 | if (count2 == 1) { 136 | if (strcmp(insn->mnemonic, insn2->mnemonic) == 0 && strcmp(insn->op_str, insn2->op_str) == 0) { 137 | count = 2; 138 | } 139 | } 140 | 141 | cs_free(insn2, count2); 142 | } 143 | 144 | if (disasm_mode == (cs_mode)(CS_MODE_THUMB)) { 145 | if (count == 2) { 146 | (*PC) += 2; 147 | opcode = opcode & 0xFFFF; 148 | } else { 149 | (*PC) += 4; 150 | } 151 | } else { 152 | (*PC) += 4; 153 | } 154 | 155 | cs_arm *arm = &(insn->detail->arm); 156 | 157 | int i; 158 | for (i = 0; i < arm->op_count; i++) { 159 | cs_arm_op *op = &(arm->operands[i]); 160 | switch((int)op->type) { 161 | default: 162 | break; 163 | case ARM_OP_IMM: 164 | { 165 | if(insn->mnemonic[0] == 'b') 166 | { 167 | if (strcmp(insn->mnemonic, "bfi") != 0 && strcmp(insn->mnemonic, "bkpt") != 0 && strncmp(insn->mnemonic, "bic", 3) != 0) { 168 | type = INSTR_TYPE_LOCAL; 169 | 170 | if (strcmp(insn->mnemonic, "bl") == 0 || strcmp(insn->mnemonic, "blx") == 0) { 171 | type = INSTR_TYPE_FUNC; 172 | } 173 | 174 | if(dwTarget) 175 | { 176 | if (strcmp(insn->mnemonic, "blx") == 0) { 177 | if (old_PC & 0x2) { 178 | op->imm -= 4; 179 | } 180 | } 181 | 182 | *dwTarget = op->imm; 183 | } 184 | } 185 | } 186 | else if(insn->mnemonic[0] == 'c' && insn->mnemonic[1] == 'b') 187 | { 188 | type = INSTR_TYPE_LOCAL; 189 | 190 | if(dwTarget) 191 | { 192 | *dwTarget = op->imm; 193 | } 194 | } 195 | 196 | break; 197 | } 198 | } 199 | } 200 | 201 | // free memory allocated by cs_disasm() 202 | cs_free(insn, ori_count); 203 | } else { 204 | (*PC) += 4; 205 | } 206 | 207 | cs_close(&handle); 208 | 209 | return type; 210 | } 211 | 212 | void disasmAddBranchSymbols(unsigned int opcode, unsigned int *PC, SymbolMap &syms) 213 | { 214 | SymbolType type; 215 | int insttype; 216 | unsigned int addr; 217 | SymbolEntry *s; 218 | char buf[128]; 219 | 220 | u32 old_PC = *PC; 221 | insttype = disasmIsBranch(opcode, PC, &addr); 222 | if(insttype != 0) 223 | { 224 | if(insttype == INSTR_TYPE_LOCAL) 225 | { 226 | snprintf(buf, sizeof(buf), "loc_%08X", addr); 227 | type = SYMBOL_LOCAL; 228 | } 229 | else 230 | { 231 | snprintf(buf, sizeof(buf), "sub_%08X", addr); 232 | type = SYMBOL_FUNC; 233 | } 234 | 235 | s = syms[addr]; 236 | if(s == NULL) 237 | { 238 | s = new SymbolEntry; 239 | s->addr = addr; 240 | s->type = type; 241 | s->size = 0; 242 | s->name = buf; 243 | s->refs.insert(s->refs.end(), old_PC); 244 | syms[addr] = s; 245 | } 246 | else 247 | { 248 | if((s->type != SYMBOL_FUNC) && (type == SYMBOL_FUNC)) 249 | { 250 | s->type = SYMBOL_FUNC; 251 | } 252 | s->refs.insert(s->refs.end(), old_PC); 253 | } 254 | } 255 | } 256 | 257 | int movw[100]; 258 | int movt[100]; 259 | 260 | void resetMovwMovt() { 261 | memset(movw, 0, sizeof(movw)); 262 | memset(movt, 0, sizeof(movt)); 263 | } 264 | 265 | int disasmAddStringRef(unsigned int opcode, unsigned int base, unsigned int size, unsigned int PC, ImmMap &imms) 266 | { 267 | int type = 0; 268 | 269 | static csh handle; 270 | cs_err err = cs_open(CS_ARCH_ARM, disasm_mode, &handle); 271 | if (err) { 272 | return 0; 273 | } 274 | 275 | cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); 276 | 277 | cs_insn *insn; 278 | size_t count = cs_disasm(handle, (unsigned char *)&opcode, 4, PC, 0, &insn); 279 | size_t ori_count = count; 280 | if (count) { 281 | if (count == 1) { 282 | cs_insn *insn2; 283 | int count2 = cs_disasm(handle, (unsigned char *)&opcode, 2, PC, 0, &insn2); 284 | if (count2 == 1) { 285 | if (strcmp(insn->mnemonic, insn2->mnemonic) == 0 && strcmp(insn->op_str, insn2->op_str) == 0) { 286 | count = 2; 287 | } 288 | } 289 | 290 | cs_free(insn2, count2); 291 | } 292 | 293 | if (disasm_mode == (cs_mode)(CS_MODE_THUMB)) { 294 | if (count == 2) { 295 | opcode = opcode & 0xFFFF; 296 | } 297 | } 298 | 299 | cs_arm *arm = &(insn->detail->arm); 300 | 301 | if (strcmp(insn->mnemonic, "movw") == 0 || strcmp(insn->mnemonic, "movs.w") == 0) { 302 | int slot = ((cs_arm_op *)&(arm->operands[0]))->imm; 303 | int val = ((cs_arm_op *)&(arm->operands[1]))->imm; 304 | movw[slot] = val; 305 | 306 | if (movt[slot] != 0) { 307 | unsigned int addr = (movt[slot] << 16) | (movw[slot] & 0xFFFF); 308 | if (addr >= base && addr < base + size) { 309 | ImmEntry *imm = new ImmEntry; 310 | imm->addr = PC; 311 | imm->target = addr; 312 | imm->text = 0; 313 | imms[PC] = imm; 314 | } 315 | 316 | movw[slot] = 0; 317 | movt[slot] = 0; 318 | } 319 | } else if (strcmp(insn->mnemonic, "movt") == 0) { 320 | int slot = ((cs_arm_op *)&(arm->operands[0]))->imm; 321 | int val = ((cs_arm_op *)&(arm->operands[1]))->imm; 322 | movt[slot] = val; 323 | 324 | if (movw[slot] != 0) { 325 | unsigned int addr = (movt[slot] << 16) | (movw[slot] & 0xFFFF); 326 | if (addr >= base && addr < base + size) { 327 | ImmEntry *imm = new ImmEntry; 328 | imm->addr = PC; 329 | imm->target = addr; 330 | imm->text = 0; 331 | imms[PC] = imm; 332 | } 333 | 334 | movw[slot] = 0; 335 | movt[slot] = 0; 336 | } 337 | } 338 | 339 | if (strcmp(insn->mnemonic, "bl") == 0 || strcmp(insn->mnemonic, "blx") == 0) { 340 | resetMovwMovt(); 341 | } 342 | 343 | // free memory allocated by cs_disasm() 344 | cs_free(insn, ori_count); 345 | } 346 | 347 | cs_close(&handle); 348 | 349 | return type; 350 | } 351 | 352 | void disasmSetHexInts(int hexints) 353 | { 354 | g_hexints = hexints; 355 | } 356 | 357 | void disasmSetMRegs(int mregs) 358 | { 359 | g_mregs = mregs; 360 | } 361 | 362 | void disasmSetSymAddr(int symaddr) 363 | { 364 | g_symaddr = symaddr; 365 | } 366 | 367 | void disasmSetMacro(int macro) 368 | { 369 | g_macroon = macro; 370 | } 371 | 372 | void disasmSetPrintReal(int printreal) 373 | { 374 | g_printreal = printreal; 375 | } 376 | 377 | void disasmSetSymbols(SymbolMap *syms) 378 | { 379 | g_syms = syms; 380 | } 381 | 382 | void disasmSetOpts(const char *opts, int set) 383 | { 384 | while(*opts) 385 | { 386 | char ch; 387 | int i; 388 | 389 | ch = *opts++; 390 | for(i = 0; i < DISASM_OPT_MAX; i++) 391 | { 392 | if(ch == g_disopts[i].opt) 393 | { 394 | *g_disopts[i].value = set; 395 | break; 396 | } 397 | } 398 | if(i == DISASM_OPT_MAX) 399 | { 400 | printf("Unknown disassembler option '%c'\n", ch); 401 | } 402 | } 403 | } 404 | 405 | void disasmPrintOpts(void) 406 | { 407 | int i; 408 | 409 | printf("Disassembler Options:\n"); 410 | for(i = 0; i < DISASM_OPT_MAX; i++) 411 | { 412 | printf("%c : %-3s - %s \n", g_disopts[i].opt, *g_disopts[i].value ? "on" : "off", 413 | g_disopts[i].name); 414 | } 415 | } 416 | 417 | void format_line(char *code, int codelen, const char *addr, unsigned int opcode, const char *name, const char *args, int noaddr) 418 | { 419 | char ascii[17]; 420 | char *p; 421 | int i; 422 | 423 | if(name == NULL) 424 | { 425 | name = "Unknown"; 426 | args = ""; 427 | } 428 | 429 | p = ascii; 430 | for(i = 0; i < 4; i++) 431 | { 432 | unsigned char ch; 433 | 434 | ch = (unsigned char) ((opcode >> (i*8)) & 0xFF); 435 | if((ch < 32) || (ch > 126)) 436 | { 437 | ch = '.'; 438 | } 439 | if(g_xmloutput && (ch == '<')) 440 | { 441 | strcpy(p, "<"); 442 | p += strlen(p); 443 | } 444 | else 445 | { 446 | *p++ = ch; 447 | } 448 | } 449 | *p = 0; 450 | 451 | if(noaddr) 452 | { 453 | snprintf(code, codelen, "%-10s %s", name, args); 454 | } 455 | else 456 | { 457 | if(g_printswap) 458 | { 459 | if(g_xmloutput) 460 | { 461 | snprintf(code, codelen, "%-10s %-80s ; %s: 0x%08X '%s'", name, args, addr, opcode, ascii); 462 | } 463 | else 464 | { 465 | snprintf(code, codelen, "%-10s %-40s ; %s: 0x%08X '%s'", name, args, addr, opcode, ascii); 466 | } 467 | } 468 | else 469 | { 470 | snprintf(code, codelen, "%s: 0x%08X '%s' - %-10s %s", addr, opcode, ascii, name, args); 471 | } 472 | } 473 | } 474 | 475 | void format_line_xml(char *code, int codelen, const char *addr, unsigned int opcode, const char *name, const char *args) 476 | { 477 | char ascii[17]; 478 | char *p; 479 | int i; 480 | 481 | if(name == NULL) 482 | { 483 | name = "Unknown"; 484 | args = ""; 485 | } 486 | 487 | p = ascii; 488 | for(i = 0; i < 4; i++) 489 | { 490 | unsigned char ch; 491 | 492 | ch = (unsigned char) ((opcode >> (i*8)) & 0xFF); 493 | if((ch < 32) || (ch > 126)) 494 | { 495 | ch = '.'; 496 | } 497 | if(g_xmloutput && (ch == '<')) 498 | { 499 | strcpy(p, "<"); 500 | p += strlen(p); 501 | } 502 | else 503 | { 504 | *p++ = ch; 505 | } 506 | } 507 | *p = 0; 508 | 509 | snprintf(code, codelen, "%s0x%08X%s", name, opcode, args); 510 | } 511 | 512 | typedef struct { 513 | const char *old_reg; 514 | const char *new_reg; 515 | } Register; 516 | 517 | Register registers[] = { 518 | { "r0", "a1" }, 519 | { "r1", "a2" }, 520 | { "r2", "a3" }, 521 | { "r3", "a4" }, 522 | 523 | { "r4", "v1" }, 524 | { "r5", "v2" }, 525 | { "r6", "v3" }, 526 | { "r7", "v4" }, 527 | { "r8", "v5" }, 528 | 529 | { "sb", "v6" }, 530 | { "sl", "v7" }, 531 | { "fp", "v8" }, 532 | }; 533 | 534 | const char *disasmInstruction(unsigned int opcode, unsigned int *PC, unsigned int *realregs, unsigned int *regmask, int nothumb) 535 | { 536 | static char code[1024]; 537 | const char *name = NULL; 538 | char mnemonic[1024]; 539 | char args[1024]; 540 | char addr[1024]; 541 | int size; 542 | int i; 543 | 544 | sprintf(addr, "0x%08X", *PC); 545 | if((g_syms) && (g_symaddr)) 546 | { 547 | char addrtemp[128]; 548 | /* Symbol resolver shouldn't touch addr unless it finds symbol */ 549 | if(disasmResolveSymbol(*PC, addrtemp, sizeof(addrtemp))) 550 | { 551 | snprintf(addr, sizeof(addr), "%-20s", addrtemp); 552 | } 553 | } 554 | 555 | cs_mode old_disasm_mode = disasm_mode; 556 | 557 | if (nothumb) { 558 | disasm_mode = (cs_mode)(CS_MODE_ARM); 559 | } 560 | 561 | static csh handle; 562 | cs_err err = cs_open(CS_ARCH_ARM, disasm_mode, &handle); 563 | if (err) { 564 | (*PC) += 4; 565 | disasm_mode = old_disasm_mode; 566 | return NULL; 567 | } 568 | 569 | cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); 570 | 571 | cs_insn *insn; 572 | size_t count = cs_disasm(handle, (unsigned char *)&opcode, 4, *PC, 0, &insn); 573 | size_t ori_count = count; 574 | if (count) { 575 | if (count == 1) { 576 | cs_insn *insn2; 577 | int count2 = cs_disasm(handle, (unsigned char *)&opcode, 2, *PC, 0, &insn2); 578 | if (count2 == 1) { 579 | if (strcmp(insn->mnemonic, insn2->mnemonic) == 0 && strcmp(insn->op_str, insn2->op_str) == 0) { 580 | count = 2; 581 | } 582 | } 583 | 584 | cs_free(insn2, count2); 585 | } 586 | 587 | strcpy(mnemonic, insn->mnemonic); 588 | strcpy(args, insn->op_str); 589 | 590 | name = mnemonic; 591 | 592 | // Replace registers 593 | int i; 594 | for(i = 0; i < strlen(insn->op_str); i++) 595 | { 596 | int j; 597 | for(j = 0; j < sizeof(registers) / sizeof(Register); j++) 598 | { 599 | if(strncmp(args + i, registers[j].old_reg, 2) == 0) 600 | { 601 | memcpy(args + i, registers[j].new_reg, 2); 602 | break; 603 | } 604 | } 605 | } 606 | 607 | // Branch names 608 | unsigned int addr; 609 | u32 lol = *PC; 610 | int insttype = disasmIsBranch(opcode, &lol, &addr); 611 | if(insttype != 0) 612 | { 613 | if(g_syms) 614 | { 615 | char args_resolved[1024]; 616 | disasmResolveSymbol(addr, args_resolved, sizeof(args_resolved)); 617 | if(insn->mnemonic[0] == 'c' && insn->mnemonic[1] == 'b') { 618 | char temp[1024]; 619 | strcpy(temp, args); 620 | char *p = strchr(temp, '#'); 621 | if (p) { 622 | strcpy(p, args_resolved); 623 | } 624 | 625 | strcpy(args, temp); 626 | } else { 627 | strcpy(args, args_resolved); 628 | } 629 | } 630 | } 631 | 632 | if (disasm_mode == (cs_mode)(CS_MODE_THUMB)) { 633 | if (count == 2) { 634 | (*PC) += 2; 635 | opcode = opcode & 0xFFFF; 636 | } else { 637 | (*PC) += 4; 638 | } 639 | } else { 640 | (*PC) += 4; 641 | } 642 | 643 | // free memory allocated by cs_disasm() 644 | cs_free(insn, ori_count); 645 | } else { 646 | (*PC) += 4; 647 | } 648 | 649 | cs_close(&handle); 650 | 651 | format_line(code, sizeof(code), addr, opcode, name, args, 0); 652 | 653 | disasm_mode = old_disasm_mode; 654 | return code; 655 | } 656 | 657 | //TODO 658 | const char *disasmInstructionXML(unsigned int opcode, unsigned int PC) 659 | { 660 | } 661 | 662 | void disasmSetXmlOutput() 663 | { 664 | g_xmloutput = 1; 665 | } 666 | -------------------------------------------------------------------------------- /disasm.h: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | * PRXTool : Utility for PSP executables. 3 | * (c) TyRaNiD 2k6 4 | * 5 | * disasm.h - Implementation of a MIPS disassembler 6 | ***************************************************************/ 7 | #ifndef __DISASM_H__ 8 | #define __DISASM_H__ 9 | 10 | #include 11 | #include 12 | #include 13 | #include "prxtypes.h" 14 | 15 | enum SymbolType 16 | { 17 | SYMBOL_NOSYM = 0, 18 | SYMBOL_UNK, 19 | SYMBOL_FUNC, 20 | SYMBOL_LOCAL, 21 | SYMBOL_DATA, 22 | }; 23 | 24 | typedef std::vector RefMap; 25 | typedef std::vector AliasMap; 26 | 27 | struct SymbolEntry 28 | { 29 | unsigned int addr; 30 | SymbolType type; 31 | unsigned int size; 32 | std::string name; 33 | RefMap refs; 34 | AliasMap alias; 35 | std::vector exported; 36 | std::vector imported; 37 | }; 38 | 39 | typedef std::map SymbolMap; 40 | 41 | struct ImmEntry 42 | { 43 | unsigned int addr; 44 | unsigned int target; 45 | /* Does this entry point to a text section ? */ 46 | int text; 47 | }; 48 | 49 | typedef std::map ImmMap; 50 | 51 | #define DISASM_OPT_MAX 8 52 | #define DISASM_OPT_HEXINTS 'x' 53 | #define DISASM_OPT_MREGS 'r' 54 | #define DISASM_OPT_SYMADDR 's' 55 | #define DISASM_OPT_MACRO 'm' 56 | #define DISASM_OPT_PRINTREAL 'p' 57 | #define DISASM_OPT_PRINTREGS 'g' 58 | #define DISASM_OPT_PRINTSWAP 'w' 59 | #define DISASM_OPT_SIGNEDHEX 'd' 60 | 61 | #define INSTR_TYPE_LOCAL 1 62 | #define INSTR_TYPE_FUNC 2 63 | 64 | void SetThumbMode(bool mode); 65 | 66 | /* Enable hexadecimal integers for immediates */ 67 | void disasmSetHexInts(int hexints); 68 | /* Enable mnemonic MIPS registers */ 69 | void disasmSetMRegs(int mregs); 70 | /* Enable resolving of PC to a symbol if available */ 71 | void disasmSetSymAddr(int symaddr); 72 | /* Enable instruction macros */ 73 | void disasmSetMacro(int macro); 74 | void disasmSetPrintReal(int printreal); 75 | void disasmSetOpts(const char *opts, int set); 76 | const char *disasmGetOpts(void); 77 | void disasmPrintOpts(void); 78 | const char *disasmInstruction(unsigned int opcode, unsigned int *PC, unsigned int *realregs, unsigned int *regmask, int nothumb); 79 | const char *disasmInstructionXML(unsigned int opcode, unsigned int PC); 80 | 81 | void disasmSetSymbols(SymbolMap *syms); 82 | void disasmAddBranchSymbols(unsigned int opcode, unsigned int *PC, SymbolMap &syms); 83 | SymbolType disasmResolveSymbol(unsigned int PC, char *name, int namelen); 84 | SymbolEntry* disasmFindSymbol(unsigned int PC); 85 | int disasmIsBranch(unsigned int opcode, unsigned int PC, unsigned int *dwTarget); 86 | void disasmSetXmlOutput(); 87 | int disasmAddStringRef(unsigned int opcode, unsigned int base, unsigned int size, unsigned int PC, ImmMap &imms); 88 | void resetMovwMovt(); 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /elftypes.h: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | * PRXTool : Utility for PSP executables. 3 | * (c) TyRaNiD 2k5 4 | * 5 | * elftypes.h - Definitions for the different ELF types. 6 | ***************************************************************/ 7 | 8 | #ifndef __ELF_TYPES_H__ 9 | #define __ELF_TYPES_H__ 10 | 11 | #include "types.h" 12 | 13 | #define ELF_SECT_MAX_NAME 128 14 | 15 | /* Structure defining a single elf section */ 16 | struct ElfSection 17 | { 18 | /* Name index */ 19 | u32 iName; 20 | /* Type of section */ 21 | u32 iType; 22 | /* Section flags */ 23 | u32 iFlags; 24 | /* Addr of section when loaded */ 25 | u32 iAddr; 26 | /* Offset of the section in the elf */ 27 | u32 iOffset; 28 | /* Size of the sections data */ 29 | u32 iSize; 30 | /* Link info */ 31 | u32 iLink; 32 | /* Info */ 33 | u32 iInfo; 34 | /* Address alignment */ 35 | u32 iAddralign; 36 | /* Entry size */ 37 | u32 iEntsize; 38 | 39 | /* Aliased pointer to the data (in the original Elf) */ 40 | u8 *pData; 41 | /* Name of the section */ 42 | char szName[ELF_SECT_MAX_NAME]; 43 | /* Pointer to the head of the relocs (if any) */ 44 | struct ElfReloc *pRelocs; 45 | /* Number of relocs for this section */ 46 | u32 iRelocCount; 47 | }; 48 | 49 | struct ElfProgram 50 | { 51 | u32 iType; 52 | u32 iOffset; 53 | u32 iVaddr; 54 | u32 iPaddr; 55 | u32 iFilesz; 56 | u32 iMemsz; 57 | u32 iFlags; 58 | u32 iAlign; 59 | 60 | /* Aliased pointer to the data (in the original Elf)*/ 61 | u8 *pData; 62 | }; 63 | 64 | /* Structure to hold elf header data, in native format */ 65 | struct ElfHeader 66 | { 67 | u32 iMagic; 68 | u32 iClass; 69 | u32 iData; 70 | u32 iIdver; 71 | u32 iType; 72 | u32 iMachine; 73 | u32 iVersion; 74 | u32 iEntry; 75 | u32 iPhoff; 76 | u32 iShoff; 77 | u32 iFlags; 78 | u32 iEhsize; 79 | u32 iPhentsize; 80 | u32 iPhnum; 81 | u32 iShentsize; 82 | u32 iShnum; 83 | u32 iShstrndx; 84 | }; 85 | 86 | struct ElfReloc 87 | { 88 | /* Pointer to the section name */ 89 | const char* secname; 90 | /* Base address */ 91 | u32 base; 92 | /* Type */ 93 | u32 type; 94 | /* Symbol (if known) */ 95 | u32 symbol; 96 | /* Offset into the file */ 97 | u32 offset; 98 | /* New Address for the relocation (to do with what you will) */ 99 | u32 info; 100 | u32 addr; 101 | }; 102 | 103 | struct ElfSymbol 104 | { 105 | const char *symname; 106 | u32 name; 107 | u32 value; 108 | u32 size; 109 | u32 info; 110 | u32 other; 111 | u32 shndx; 112 | }; 113 | 114 | /* Define ELF types */ 115 | typedef u32 Elf32_Addr; 116 | typedef u16 Elf32_Half; 117 | typedef u32 Elf32_Off; 118 | typedef s32 Elf32_Sword; 119 | typedef u32 Elf32_Word; 120 | 121 | #define ELF_MAGIC 0x464C457F 122 | 123 | #define ELF_MIPS_TYPE 0x0002 124 | #define ELF_PRX_TYPE 0xFE04 125 | 126 | #define SHT_NULL 0 127 | #define SHT_PROGBITS 1 128 | #define SHT_SYMTAB 2 129 | #define SHT_STRTAB 3 130 | #define SHT_RELA 4 131 | #define SHT_HASH 5 132 | #define SHT_DYNAMIC 6 133 | #define SHT_NOTE 7 134 | #define SHT_NOBITS 8 135 | #define SHT_REL 9 136 | #define SHT_SHLIB 10 137 | #define SHT_DYNSYM 11 138 | #define SHT_LOPROC 0x70000000 139 | #define SHT_HIPROC 0x7fffffff 140 | #define SHT_LOUSER 0x80000000 141 | #define SHT_HIUSER 0xffffffff 142 | 143 | #define SHF_WRITE 1 144 | #define SHF_ALLOC 2 145 | #define SHF_EXECINSTR 4 146 | 147 | #define PT_NULL 0 148 | #define PT_LOAD 1 149 | #define PT_DYNAMIC 2 150 | #define PT_INTERP 3 151 | #define PT_NOTE 4 152 | #define PT_SHLIB 5 153 | #define PT_PHDR 6 154 | #define PT_LOPROC 0x70000000 155 | #define PT_HIPROC 0x7fffffff 156 | 157 | #define PT_SCE_RELA 0x60000000 158 | 159 | /** \name SCE Relocation 160 | * @{ 161 | */ 162 | typedef union sce_reloc 163 | { 164 | u32 r_type; 165 | struct 166 | { 167 | u32 r_opt1; 168 | u32 r_opt2; 169 | } r_short; 170 | struct 171 | { 172 | u32 r_type; 173 | u32 r_addend; 174 | u32 r_offset; 175 | } r_long; 176 | } sce_reloc_t; 177 | /** @}*/ 178 | 179 | /** \name Macros to get SCE reloc values 180 | * @{ 181 | */ 182 | #define SCE_RELOC_SHORT_OFFSET(x) (((x).r_opt1 >> 20) | ((x).r_opt2 & 0xFFFFF) << 12) 183 | #define SCE_RELOC_SHORT_ADDEND(x) ((x).r_opt2 >> 20) 184 | #define SCE_RELOC_LONG_OFFSET(x) ((x).r_offset) 185 | #define SCE_RELOC_LONG_ADDEND(x) ((x).r_addend) 186 | #define SCE_RELOC_LONG_CODE2(x) (((x).r_type >> 20) & 0xFF) 187 | #define SCE_RELOC_LONG_DIST2(x) (((x).r_type >> 28) & 0xF) 188 | #define SCE_RELOC_IS_SHORT(x) (((x).r_type) & 0xF) 189 | #define SCE_RELOC_CODE(x) (((x).r_type >> 8) & 0xFF) 190 | #define SCE_RELOC_SYMSEG(x) (((x).r_type >> 4) & 0xF) 191 | #define SCE_RELOC_DATSEG(x) (((x).r_type >> 16) & 0xF) 192 | /** @}*/ 193 | 194 | /** \name Vita supported relocations 195 | * @{ 196 | */ 197 | #define R_ARM_NONE 0 198 | #define R_ARM_ABS32 2 199 | #define R_ARM_REL32 3 200 | #define R_ARM_THM_CALL 10 201 | #define R_ARM_CALL 28 202 | #define R_ARM_JUMP24 29 203 | #define R_ARM_TARGET1 38 204 | #define R_ARM_V4BX 40 205 | #define R_ARM_TARGET2 41 206 | #define R_ARM_PREL31 42 207 | #define R_ARM_MOVW_ABS_NC 43 208 | #define R_ARM_MOVT_ABS 44 209 | #define R_ARM_THM_MOVW_ABS_NC 47 210 | #define R_ARM_THM_MOVT_ABS 48 211 | /** @}*/ 212 | 213 | /* ELF file header */ 214 | typedef struct { 215 | Elf32_Word e_magic; 216 | u8 e_class; 217 | u8 e_data; 218 | u8 e_idver; 219 | u8 e_pad[9]; 220 | Elf32_Half e_type; 221 | Elf32_Half e_machine; 222 | Elf32_Word e_version; 223 | Elf32_Addr e_entry; 224 | Elf32_Off e_phoff; 225 | Elf32_Off e_shoff; 226 | Elf32_Word e_flags; 227 | Elf32_Half e_ehsize; 228 | Elf32_Half e_phentsize; 229 | Elf32_Half e_phnum; 230 | Elf32_Half e_shentsize; 231 | Elf32_Half e_shnum; 232 | Elf32_Half e_shstrndx; 233 | } __attribute__((packed)) Elf32_Ehdr; 234 | 235 | /* ELF section header */ 236 | typedef struct { 237 | Elf32_Word sh_name; 238 | Elf32_Word sh_type; 239 | Elf32_Word sh_flags; 240 | Elf32_Addr sh_addr; 241 | Elf32_Off sh_offset; 242 | Elf32_Word sh_size; 243 | Elf32_Word sh_link; 244 | Elf32_Word sh_info; 245 | Elf32_Word sh_addralign; 246 | Elf32_Word sh_entsize; 247 | } __attribute__((packed)) Elf32_Shdr; 248 | 249 | typedef struct { 250 | Elf32_Word p_type; 251 | Elf32_Off p_offset; 252 | Elf32_Addr p_vaddr; 253 | Elf32_Addr p_paddr; 254 | Elf32_Word p_filesz; 255 | Elf32_Word p_memsz; 256 | Elf32_Word p_flags; 257 | Elf32_Word p_align; 258 | } Elf32_Phdr; 259 | 260 | #define ELF32_R_SYM(i) ((i)>>8) 261 | #define ELF32_R_TYPE(i) ((u8)(i&0xFF)) 262 | 263 | typedef struct { 264 | Elf32_Addr r_offset; 265 | Elf32_Word r_info; 266 | } Elf32_Rel; 267 | 268 | #define ELF32_ST_BIND(i) ((i)>>4) 269 | #define ELF32_ST_TYPE(i) ((i)&0xf) 270 | #define ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf)) 271 | 272 | #define STT_NOTYPE 0 273 | #define STT_OBJECT 1 274 | #define STT_FUNC 2 275 | #define STT_SECTION 3 276 | #define STT_FILE 4 277 | #define STT_LOPROC 13 278 | #define STT_HIPROC 15 279 | 280 | typedef struct { 281 | Elf32_Word st_name; 282 | Elf32_Addr st_value; 283 | Elf32_Word st_size; 284 | unsigned char st_info; 285 | unsigned char st_other; 286 | Elf32_Half st_shndx; 287 | } __attribute__((packed)) Elf32_Sym; 288 | 289 | #endif 290 | -------------------------------------------------------------------------------- /getargs.C: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | * PRXTool : Utility for PSP executables. 3 | * (c) TyRaNiD 2k5 4 | * 5 | * getargs.C - Argument parser 6 | ***************************************************************/ 7 | #include 8 | #include 9 | #include 10 | #include "getargs.h" 11 | 12 | char **GetArgs(int *argc, char **argv, struct ArgEntry *entry, int argcount) 13 | { 14 | int error = 0; 15 | 16 | if((argc == NULL) || (argv == NULL) || (entry == NULL)) 17 | { 18 | return NULL; 19 | } 20 | 21 | (*argc)--; 22 | argv++; 23 | 24 | while(*argc > 0) 25 | { 26 | const char *arg; 27 | struct ArgEntry *ent; 28 | 29 | if(*argv == NULL) 30 | { 31 | error = 1; 32 | break; 33 | } 34 | arg = *argv; 35 | 36 | if(arg[0] != '-') 37 | { 38 | break; 39 | } 40 | 41 | if(arg[1] == '-') 42 | { 43 | /* Long arg */ 44 | int i; 45 | 46 | ent = NULL; 47 | for(i = 0; i < argcount; i++) 48 | { 49 | if(entry[i].full) 50 | { 51 | if(strcmp(entry[i].full, &arg[2]) == 0) 52 | { 53 | ent = &entry[i]; 54 | } 55 | } 56 | } 57 | } 58 | else if(arg[1] != 0) 59 | { 60 | int i; 61 | 62 | ent = NULL; 63 | 64 | /* Error check, short options should be 2 characters */ 65 | if(strlen(arg) == 2) 66 | { 67 | for(i = 0; i < argcount; i++) 68 | { 69 | if(entry[i].ch == arg[1]) 70 | { 71 | ent = &entry[i]; 72 | } 73 | } 74 | } 75 | } 76 | else 77 | { 78 | /* Single - means stop processing */ 79 | (*argc)--; 80 | argv++; 81 | break; 82 | } 83 | 84 | if(ent == NULL) 85 | { 86 | fprintf(stderr, "Invalid argument %s\n", arg); 87 | error = 1; 88 | break; 89 | } 90 | 91 | if(ent->argvoid == NULL) 92 | { 93 | fprintf(stderr, "Internal error processing %s\n", arg); 94 | error = 1; 95 | break; 96 | } 97 | 98 | if(ent->opt == ARG_OPT_NONE) 99 | { 100 | switch(ent->type) 101 | { 102 | case ARG_TYPE_BOOL: { 103 | bool *argbool = (bool *) ent->argvoid; 104 | *argbool = ent->val; 105 | } 106 | break; 107 | case ARG_TYPE_INT: { 108 | int *argint = (int *) ent->argvoid; 109 | *argint = ent->val; 110 | } 111 | break; 112 | case ARG_TYPE_FUNC: { ArgFunc argfunc = (ArgFunc) ent->argvoid; 113 | if(argfunc(NULL) == 0) 114 | { 115 | fprintf(stderr, "Error processing argument for %s\n", arg); 116 | error = 1; 117 | } 118 | } 119 | break; 120 | default: fprintf(stderr, "Invalid type for option %s\n", arg); 121 | error = 1; 122 | break; 123 | }; 124 | 125 | if(error) 126 | { 127 | break; 128 | } 129 | } 130 | else if(ent->opt == ARG_OPT_REQUIRED) 131 | { 132 | if(*argc <= 1) 133 | { 134 | fprintf(stderr, "No argument passed for %s\n", arg); 135 | error = 1; 136 | break; 137 | } 138 | (*argc)--; 139 | argv++; 140 | 141 | switch(ent->type) 142 | { 143 | case ARG_TYPE_INT: { int *argint = (int*) ent->argvoid; 144 | *argint = strtoul(argv[0], NULL, 0); 145 | } 146 | break; 147 | case ARG_TYPE_STR: { const char **argstr = (const char **) ent->argvoid; 148 | *argstr = argv[0]; 149 | } 150 | break; 151 | case ARG_TYPE_FUNC: { ArgFunc argfunc = (ArgFunc) ent->argvoid; 152 | if(argfunc(argv[0]) == 0) 153 | { 154 | fprintf(stderr, "Error processing argument for %s\n", arg); 155 | error = 1; 156 | } 157 | } 158 | break; 159 | default: fprintf(stderr, "Invalid type for option %s\n", arg); 160 | error = 1; 161 | break; 162 | }; 163 | 164 | if(error) 165 | { 166 | break; 167 | } 168 | } 169 | else 170 | { 171 | fprintf(stderr, "Internal options error processing %s\n", arg); 172 | error = 1; 173 | break; 174 | } 175 | 176 | (*argc)--; 177 | argv++; 178 | } 179 | 180 | if(error) 181 | { 182 | return NULL; 183 | } 184 | else 185 | { 186 | return argv; 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /getargs.h: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | * PRXTool : Utility for PSP executables. 3 | * (c) TyRaNiD 2k5 4 | * 5 | * getargs.h - Argument parser 6 | ***************************************************************/ 7 | #ifndef __GET_ARGS_H__ 8 | #define __GET_ARGS_H__ 9 | /* Replacement for getopt_long as I think it sucks ;P */ 10 | 11 | typedef int (*ArgFunc)(const char *opt); 12 | 13 | enum ArgTypes 14 | { 15 | ARG_TYPE_INT, 16 | ARG_TYPE_BOOL, 17 | ARG_TYPE_STR, 18 | ARG_TYPE_FUNC, 19 | }; 20 | 21 | enum ArgOpts 22 | { 23 | ARG_OPT_NONE, 24 | ARG_OPT_REQUIRED, 25 | }; 26 | 27 | struct ArgEntry 28 | { 29 | const char *full; 30 | char ch; 31 | enum ArgTypes type; 32 | enum ArgOpts opt; 33 | void *argvoid; 34 | int val; 35 | const char *help; 36 | }; 37 | 38 | #define ARG_COUNT(x) (sizeof(x) / sizeof(struct ArgEntry)) 39 | 40 | char** GetArgs(int *argc, char **argv, struct ArgEntry *entry, int argcount); 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /output.C: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | * PRXTool : Utility for PSP executables. 3 | * (c) TyRaNiD 2k5 4 | * 5 | * Output.C - Static class to handle information and debug 6 | * textual output. 7 | ***************************************************************/ 8 | 9 | #include 10 | #include 11 | #include "output.h" 12 | 13 | bool COutput::m_blDebug = false; 14 | OutputHandler COutput::m_fnOutput = NULL; 15 | 16 | void COutput::SetDebug(bool blDebug) 17 | { 18 | m_blDebug = blDebug; 19 | } 20 | 21 | bool COutput::GetDebug() 22 | { 23 | return m_blDebug; 24 | } 25 | 26 | void COutput::SetOutputHandler(OutputHandler fn) 27 | { 28 | m_fnOutput = fn; 29 | } 30 | 31 | void COutput::Puts(OutputLevel level, const char *str) 32 | { 33 | Printf(level, "%s\n", str); 34 | } 35 | 36 | void COutput::Printf(OutputLevel level, const char *str, ...) 37 | { 38 | va_list opt; 39 | char buff[2048]; 40 | 41 | va_start(opt, str); 42 | (void) vsnprintf(buff, (size_t) sizeof(buff), str, opt); 43 | 44 | if(m_fnOutput != NULL) 45 | { 46 | if((level != LEVEL_DEBUG) || (m_blDebug)) 47 | { 48 | m_fnOutput(level, buff); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /output.h: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | * PRXTool : Utility for PSP executables. 3 | * (c) TyRaNiD 2k5 4 | * 5 | * output.h - Definition of a class to handle textual output. 6 | ***************************************************************/ 7 | 8 | #ifndef __OUTPUT_H__ 9 | #define __OUTPUT_H__ 10 | 11 | enum OutputLevel 12 | { 13 | LEVEL_INFO = 0, 14 | LEVEL_WARNING = 1, 15 | LEVEL_ERROR = 2, 16 | LEVEL_DEBUG = 3 17 | }; 18 | 19 | typedef void (*OutputHandler)(OutputLevel level, const char *szDebug); 20 | 21 | class COutput 22 | { 23 | /* Enables debug output */ 24 | static bool m_blDebug; 25 | static OutputHandler m_fnOutput; 26 | COutput() {}; 27 | ~COutput() {}; 28 | public: 29 | static void SetDebug(bool blDebug); 30 | static bool GetDebug(); 31 | static void SetOutputHandler(OutputHandler fn); 32 | static void Puts(OutputLevel level, const char *str); 33 | static void Printf(OutputLevel level, const char *str, ...); 34 | }; 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /prxtypes.h: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | * PRXTool : Utility for PSP executables. 3 | * (c) TyRaNiD 2k5 4 | * 5 | * prxtypes.h - Definition of PRX specific types. 6 | ***************************************************************/ 7 | 8 | #ifndef __PRXTYPES_H__ 9 | #define __PRXTYPES_H__ 10 | 11 | #include 12 | #include "types.h" 13 | 14 | #define PSP_MODULE_MAX_NAME 28 15 | #define PSP_LIB_MAX_NAME 128 16 | #define PSP_ENTRY_MAX_NAME 128 17 | /* Define the maximum number of permitted entries per lib */ 18 | #define PSP_MAX_V_ENTRIES 255 19 | #define PSP_MAX_F_ENTRIES 4096 20 | 21 | #define PSP_MODULE_INFO_NAME ".sceModuleInfo.rodata" 22 | 23 | /* Define a name for the unnamed first export */ 24 | #define PSP_SYSTEM_EXPORT "syslib" 25 | 26 | enum PspEntryType 27 | { 28 | PSP_ENTRY_FUNC = 0, 29 | PSP_ENTRY_VAR = 1 30 | }; 31 | 32 | /* Define the in-prx structure types */ 33 | 34 | /* Structure to hold the module export information */ 35 | struct PspModuleExport 36 | { 37 | u16 size; 38 | u16 version; 39 | u16 flags; 40 | u16 f_count; 41 | u32 v_count; 42 | u32 u_count; 43 | u32 nid; 44 | u32 name; 45 | u32 export_nids; 46 | u32 export_entry_table; 47 | }; 48 | 49 | /* Structure to hold the module import information */ 50 | 51 | struct PspModuleImport2xx 52 | { 53 | u16 size; 54 | u16 version; 55 | u16 flags; 56 | u16 f_count; 57 | u16 v_count; 58 | u16 u_count; 59 | u32 reserved1; 60 | u32 nid; 61 | u32 name; 62 | u32 reserved2; 63 | u32 func_nids; 64 | u32 func_entry_table; 65 | u32 var_nids; 66 | u32 var_entry_table; 67 | u32 unk_nids; 68 | u32 unk_entry_table; 69 | }; 70 | 71 | struct PspModuleImport3xx 72 | { 73 | u16 size; 74 | u16 version; 75 | u16 flags; 76 | u16 f_count; 77 | u16 v_count; 78 | u16 reserved1; 79 | u32 nid; 80 | u32 name; 81 | u32 func_nids; 82 | u32 func_entry_table; 83 | u32 var_nids; 84 | u32 var_entry_table; 85 | }; 86 | 87 | /* Structure to hold the module info */ 88 | struct PspModuleInfo 89 | { 90 | u16 flags; 91 | u16 version; 92 | char name[PSP_MODULE_MAX_NAME-1]; 93 | u8 type; 94 | u32 gp; 95 | u32 exports; 96 | u32 exp_end; 97 | u32 imports; 98 | u32 imp_end; 99 | }; 100 | 101 | /* Define the loaded prx types */ 102 | struct PspEntry 103 | { 104 | /* Name of the entry */ 105 | char name[PSP_ENTRY_MAX_NAME]; 106 | /* Nid of the entry */ 107 | u32 nid; 108 | /* Type of the entry */ 109 | PspEntryType type; 110 | /* Virtual address of the entry in the loaded elf */ 111 | u32 addr; 112 | /* Virtual address of the nid dword */ 113 | u32 nid_addr; 114 | }; 115 | 116 | /* Holds a linking entry for an import library */ 117 | struct PspLibImport 118 | { 119 | /** Previous import */ 120 | PspLibImport *prev; 121 | /** Next import */ 122 | PspLibImport *next; 123 | /** Name of the library */ 124 | char name[PSP_LIB_MAX_NAME]; 125 | /** Virtual address of the lib import stub */ 126 | u32 addr; 127 | /** Copy of the import stub (in native byte order) */ 128 | PspModuleImport2xx stub; 129 | /** List of function entries */ 130 | PspEntry funcs[PSP_MAX_F_ENTRIES]; 131 | /** Number of function entries */ 132 | int f_count; 133 | /** List of variable entried */ 134 | PspEntry vars[PSP_MAX_V_ENTRIES]; 135 | /** Number of variable entries */ 136 | int v_count; 137 | /** File containing the export */ 138 | char file[PATH_MAX]; 139 | }; 140 | 141 | /* Holds a linking entry for an export library */ 142 | struct PspLibExport 143 | { 144 | /** Previous export in the chain */ 145 | PspLibExport *prev; 146 | /** Next export in the chain */ 147 | PspLibExport *next; 148 | /** Name of the library */ 149 | char name[PSP_LIB_MAX_NAME]; 150 | /** Virtual address of the lib import stub */ 151 | u32 addr; 152 | /** Copy of the import stub (in native byte order) */ 153 | PspModuleExport stub; 154 | /** List of function entries */ 155 | PspEntry funcs[PSP_MAX_F_ENTRIES]; 156 | /** Number of function entries */ 157 | int f_count; 158 | /** List of variable entried */ 159 | PspEntry vars[PSP_MAX_V_ENTRIES]; 160 | /** Number of variable entires */ 161 | int v_count; 162 | }; 163 | 164 | /** Structure to hold the loaded module information */ 165 | struct PspModule 166 | { 167 | /** Name of the module */ 168 | char name[PSP_MODULE_MAX_NAME]; 169 | /** Info structure, in native byte order */ 170 | PspModuleInfo info; 171 | /** Virtual address of the module info section */ 172 | u32 addr; 173 | /** Head of the export list */ 174 | PspLibExport *exp_head; 175 | /** Head of the import list */ 176 | PspLibImport *imp_head; 177 | }; 178 | 179 | #define SYMFILE_MAGIC "SYMS" 180 | 181 | struct SymfileHeader 182 | { 183 | char magic[4]; 184 | char modname[PSP_MODULE_MAX_NAME]; 185 | u32 symcount; 186 | u32 strstart; 187 | u32 strsize; 188 | } __attribute__((packed)); 189 | 190 | struct SymfileEntry 191 | { 192 | u32 name; 193 | u32 addr; 194 | u32 size; 195 | } __attribute__((packed)); 196 | 197 | #endif 198 | -------------------------------------------------------------------------------- /pspkerror.C: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | * PRXTool : Utility for PSP executables. 3 | * (c) TyRaNiD 2k5 4 | * 5 | * pspkerror.C - Definitions for error codes 6 | ***************************************************************/ 7 | #include "pspkerror.h" 8 | 9 | struct PspErrorCode PspKernelErrorCodes[] = 10 | { 11 | { "SCE_KERNEL_ERROR_OK" , 0 }, 12 | { "SCE_KERNEL_ERROR_ERROR" , 0x80020001 }, 13 | { "SCE_KERNEL_ERROR_NOTIMP" , 0x80020002 }, 14 | { "SCE_KERNEL_ERROR_ILLEGAL_EXPCODE" , 0x80020032 }, 15 | { "SCE_KERNEL_ERROR_EXPHANDLER_NOUSE" , 0x80020033 }, 16 | { "SCE_KERNEL_ERROR_EXPHANDLER_USED" , 0x80020034 }, 17 | { "SCE_KERNEL_ERROR_SYCALLTABLE_NOUSED" , 0x80020035 }, 18 | { "SCE_KERNEL_ERROR_SYCALLTABLE_USED" , 0x80020036 }, 19 | { "SCE_KERNEL_ERROR_ILLEGAL_SYSCALLTABLE" , 0x80020037 }, 20 | { "SCE_KERNEL_ERROR_ILLEGAL_PRIMARY_SYSCALL_NUMBER" , 0x80020038 }, 21 | { "SCE_KERNEL_ERROR_PRIMARY_SYSCALL_NUMBER_INUSE" , 0x80020039 }, 22 | { "SCE_KERNEL_ERROR_ILLEGAL_CONTEXT" , 0x80020064 }, 23 | { "SCE_KERNEL_ERROR_ILLEGAL_INTRCODE" , 0x80020065 }, 24 | { "SCE_KERNEL_ERROR_CPUDI" , 0x80020066 }, 25 | { "SCE_KERNEL_ERROR_FOUND_HANDLER" , 0x80020067 }, 26 | { "SCE_KERNEL_ERROR_NOTFOUND_HANDLER" , 0x80020068 }, 27 | { "SCE_KERNEL_ERROR_ILLEGAL_INTRLEVEL" , 0x80020069 }, 28 | { "SCE_KERNEL_ERROR_ILLEGAL_ADDRESS" , 0x8002006a }, 29 | { "SCE_KERNEL_ERROR_ILLEGAL_INTRPARAM" , 0x8002006b }, 30 | { "SCE_KERNEL_ERROR_ILLEGAL_STACK_ADDRESS" , 0x8002006c }, 31 | { "SCE_KERNEL_ERROR_ALREADY_STACK_SET" , 0x8002006d }, 32 | { "SCE_KERNEL_ERROR_NO_TIMER" , 0x80020096 }, 33 | { "SCE_KERNEL_ERROR_ILLEGAL_TIMERID" , 0x80020097 }, 34 | { "SCE_KERNEL_ERROR_ILLEGAL_SOURCE" , 0x80020098 }, 35 | { "SCE_KERNEL_ERROR_ILLEGAL_PRESCALE" , 0x80020099 }, 36 | { "SCE_KERNEL_ERROR_TIMER_BUSY" , 0x8002009a }, 37 | { "SCE_KERNEL_ERROR_TIMER_NOT_SETUP" , 0x8002009b }, 38 | { "SCE_KERNEL_ERROR_TIMER_NOT_INUSE" , 0x8002009c }, 39 | { "SCE_KERNEL_ERROR_UNIT_USED" , 0x800200a0 }, 40 | { "SCE_KERNEL_ERROR_UNIT_NOUSE" , 0x800200a1 }, 41 | { "SCE_KERNEL_ERROR_NO_ROMDIR" , 0x800200a2 }, 42 | { "SCE_KERNEL_ERROR_IDTYPE_EXIST" , 0x800200c8 }, 43 | { "SCE_KERNEL_ERROR_IDTYPE_NOT_EXIST" , 0x800200c9 }, 44 | { "SCE_KERNEL_ERROR_IDTYPE_NOT_EMPTY" , 0x800200ca }, 45 | { "SCE_KERNEL_ERROR_UNKNOWN_UID" , 0x800200cb }, 46 | { "SCE_KERNEL_ERROR_UNMATCH_UID_TYPE" , 0x800200cc }, 47 | { "SCE_KERNEL_ERROR_ID_NOT_EXIST" , 0x800200cd }, 48 | { "SCE_KERNEL_ERROR_NOT_FOUND_UIDFUNC" , 0x800200ce }, 49 | { "SCE_KERNEL_ERROR_UID_ALREADY_HOLDER" , 0x800200cf }, 50 | { "SCE_KERNEL_ERROR_UID_NOT_HOLDER" , 0x800200d0 }, 51 | { "SCE_KERNEL_ERROR_ILLEGAL_PERM" , 0x800200d1 }, 52 | { "SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT" , 0x800200d2 }, 53 | { "SCE_KERNEL_ERROR_ILLEGAL_ADDR" , 0x800200d3 }, 54 | { "SCE_KERNEL_ERROR_OUT_OF_RANGE" , 0x800200d4 }, 55 | { "SCE_KERNEL_ERROR_MEM_RANGE_OVERLAP" , 0x800200d5 }, 56 | { "SCE_KERNEL_ERROR_ILLEGAL_PARTITION" , 0x800200d6 }, 57 | { "SCE_KERNEL_ERROR_PARTITION_INUSE" , 0x800200d7 }, 58 | { "SCE_KERNEL_ERROR_ILLEGAL_MEMBLOCKTYPE" , 0x800200d8 }, 59 | { "SCE_KERNEL_ERROR_MEMBLOCK_ALLOC_FAILED" , 0x800200d9 }, 60 | { "SCE_KERNEL_ERROR_MEMBLOCK_RESIZE_LOCKED" , 0x800200da }, 61 | { "SCE_KERNEL_ERROR_MEMBLOCK_RESIZE_FAILED" , 0x800200db }, 62 | { "SCE_KERNEL_ERROR_HEAPBLOCK_ALLOC_FAILED" , 0x800200dc }, 63 | { "SCE_KERNEL_ERROR_HEAP_ALLOC_FAILED" , 0x800200dd }, 64 | { "SCE_KERNEL_ERROR_ILLEGAL_CHUNK_ID" , 0x800200de }, 65 | { "SCE_KERNEL_ERROR_NOCHUNK" , 0x800200df }, 66 | { "SCE_KERNEL_ERROR_NO_FREECHUNK" , 0x800200e0 }, 67 | { "SCE_KERNEL_ERROR_LINKERR" , 0x8002012c }, 68 | { "SCE_KERNEL_ERROR_ILLEGAL_OBJECT" , 0x8002012d }, 69 | { "SCE_KERNEL_ERROR_UNKNOWN_MODULE" , 0x8002012e }, 70 | { "SCE_KERNEL_ERROR_NOFILE" , 0x8002012f }, 71 | { "SCE_KERNEL_ERROR_FILEERR" , 0x80020130 }, 72 | { "SCE_KERNEL_ERROR_MEMINUSE" , 0x80020131 }, 73 | { "SCE_KERNEL_ERROR_PARTITION_MISMATCH" , 0x80020132 }, 74 | { "SCE_KERNEL_ERROR_ALREADY_STARTED" , 0x80020133 }, 75 | { "SCE_KERNEL_ERROR_NOT_STARTED" , 0x80020134 }, 76 | { "SCE_KERNEL_ERROR_ALREADY_STOPPED" , 0x80020135 }, 77 | { "SCE_KERNEL_ERROR_CAN_NOT_STOP" , 0x80020136 }, 78 | { "SCE_KERNEL_ERROR_NOT_STOPPED" , 0x80020137 }, 79 | { "SCE_KERNEL_ERROR_NOT_REMOVABLE" , 0x80020138 }, 80 | { "SCE_KERNEL_ERROR_EXCLUSIVE_LOAD" , 0x80020139 }, 81 | { "SCE_KERNEL_ERROR_LIBRARY_NOT_YET_LINKED" , 0x8002013a }, 82 | { "SCE_KERNEL_ERROR_LIBRARY_FOUND" , 0x8002013b }, 83 | { "SCE_KERNEL_ERROR_LIBRARY_NOTFOUND" , 0x8002013c }, 84 | { "SCE_KERNEL_ERROR_ILLEGAL_LIBRARY" , 0x8002013d }, 85 | { "SCE_KERNEL_ERROR_LIBRARY_INUSE" , 0x8002013e }, 86 | { "SCE_KERNEL_ERROR_ALREADY_STOPPING" , 0x8002013f }, 87 | { "SCE_KERNEL_ERROR_ILLEGAL_OFFSET" , 0x80020140 }, 88 | { "SCE_KERNEL_ERROR_ILLEGAL_POSITION" , 0x80020141 }, 89 | { "SCE_KERNEL_ERROR_ILLEGAL_ACCESS" , 0x80020142 }, 90 | { "SCE_KERNEL_ERROR_MODULE_MGR_BUSY" , 0x80020143 }, 91 | { "SCE_KERNEL_ERROR_ILLEGAL_FLAG" , 0x80020144 }, 92 | { "SCE_KERNEL_ERROR_CANNOT_GET_MODULELIST" , 0x80020145 }, 93 | { "SCE_KERNEL_ERROR_PROHIBIT_LOADMODULE_DEVICE" , 0x80020146 }, 94 | { "SCE_KERNEL_ERROR_PROHIBIT_LOADEXEC_DEVICE" , 0x80020147 }, 95 | { "SCE_KERNEL_ERROR_UNSUPPORTED_PRX_TYPE" , 0x80020148 }, 96 | { "SCE_KERNEL_ERROR_ILLEGAL_PERM_CALL" , 0x80020149 }, 97 | { "SCE_KERNEL_ERROR_CANNOT_GET_MODULE_INFORMATION" , 0x8002014a }, 98 | { "SCE_KERNEL_ERROR_ILLEGAL_LOADEXEC_BUFFER" , 0x8002014b }, 99 | { "SCE_KERNEL_ERROR_ILLEGAL_LOADEXEC_FILENAME" , 0x8002014c }, 100 | { "SCE_KERNEL_ERROR_NO_EXIT_CALLBACK" , 0x8002014d }, 101 | { "SCE_KERNEL_ERROR_NO_MEMORY" , 0x80020190 }, 102 | { "SCE_KERNEL_ERROR_ILLEGAL_ATTR" , 0x80020191 }, 103 | { "SCE_KERNEL_ERROR_ILLEGAL_ENTRY" , 0x80020192 }, 104 | { "SCE_KERNEL_ERROR_ILLEGAL_PRIORITY" , 0x80020193 }, 105 | { "SCE_KERNEL_ERROR_ILLEGAL_STACK_SIZE" , 0x80020194 }, 106 | { "SCE_KERNEL_ERROR_ILLEGAL_MODE" , 0x80020195 }, 107 | { "SCE_KERNEL_ERROR_ILLEGAL_MASK" , 0x80020196 }, 108 | { "SCE_KERNEL_ERROR_ILLEGAL_THID" , 0x80020197 }, 109 | { "SCE_KERNEL_ERROR_UNKNOWN_THID" , 0x80020198 }, 110 | { "SCE_KERNEL_ERROR_UNKNOWN_SEMID" , 0x80020199 }, 111 | { "SCE_KERNEL_ERROR_UNKNOWN_EVFID" , 0x8002019a }, 112 | { "SCE_KERNEL_ERROR_UNKNOWN_MBXID" , 0x8002019b }, 113 | { "SCE_KERNEL_ERROR_UNKNOWN_VPLID" , 0x8002019c }, 114 | { "SCE_KERNEL_ERROR_UNKNOWN_FPLID" , 0x8002019d }, 115 | { "SCE_KERNEL_ERROR_UNKNOWN_MPPID" , 0x8002019e }, 116 | { "SCE_KERNEL_ERROR_UNKNOWN_ALMID" , 0x8002019f }, 117 | { "SCE_KERNEL_ERROR_UNKNOWN_TEID" , 0x800201a0 }, 118 | { "SCE_KERNEL_ERROR_UNKNOWN_CBID" , 0x800201a1 }, 119 | { "SCE_KERNEL_ERROR_DORMANT" , 0x800201a2 }, 120 | { "SCE_KERNEL_ERROR_SUSPEND" , 0x800201a3 }, 121 | { "SCE_KERNEL_ERROR_NOT_DORMANT" , 0x800201a4 }, 122 | { "SCE_KERNEL_ERROR_NOT_SUSPEND" , 0x800201a5 }, 123 | { "SCE_KERNEL_ERROR_NOT_WAIT" , 0x800201a6 }, 124 | { "SCE_KERNEL_ERROR_CAN_NOT_WAIT" , 0x800201a7 }, 125 | { "SCE_KERNEL_ERROR_WAIT_TIMEOUT" , 0x800201a8 }, 126 | { "SCE_KERNEL_ERROR_WAIT_CANCEL" , 0x800201a9 }, 127 | { "SCE_KERNEL_ERROR_RELEASE_WAIT" , 0x800201aa }, 128 | { "SCE_KERNEL_ERROR_NOTIFY_CALLBACK" , 0x800201ab }, 129 | { "SCE_KERNEL_ERROR_THREAD_TERMINATED" , 0x800201ac }, 130 | { "SCE_KERNEL_ERROR_SEMA_ZERO" , 0x800201ad }, 131 | { "SCE_KERNEL_ERROR_SEMA_OVF" , 0x800201ae }, 132 | { "SCE_KERNEL_ERROR_EVF_COND" , 0x800201af }, 133 | { "SCE_KERNEL_ERROR_EVF_MULTI" , 0x800201b0 }, 134 | { "SCE_KERNEL_ERROR_EVF_ILPAT" , 0x800201b1 }, 135 | { "SCE_KERNEL_ERROR_MBOX_NOMSG" , 0x800201b2 }, 136 | { "SCE_KERNEL_ERROR_MPP_FULL" , 0x800201b3 }, 137 | { "SCE_KERNEL_ERROR_MPP_EMPTY" , 0x800201b4 }, 138 | { "SCE_KERNEL_ERROR_WAIT_DELETE" , 0x800201b5 }, 139 | { "SCE_KERNEL_ERROR_ILLEGAL_MEMBLOCK" , 0x800201b6 }, 140 | { "SCE_KERNEL_ERROR_ILLEGAL_MEMSIZE" , 0x800201b7 }, 141 | { "SCE_KERNEL_ERROR_ILLEGAL_SPADADDR" , 0x800201b8 }, 142 | { "SCE_KERNEL_ERROR_SPAD_INUSE" , 0x800201b9 }, 143 | { "SCE_KERNEL_ERROR_SPAD_NOT_INUSE" , 0x800201ba }, 144 | { "SCE_KERNEL_ERROR_ILLEGAL_TYPE" , 0x800201bb }, 145 | { "SCE_KERNEL_ERROR_ILLEGAL_SIZE" , 0x800201bc }, 146 | { "SCE_KERNEL_ERROR_ILLEGAL_COUNT" , 0x800201bd }, 147 | { "SCE_KERNEL_ERROR_UNKNOWN_VTID" , 0x800201be }, 148 | { "SCE_KERNEL_ERROR_ILLEGAL_VTID" , 0x800201bf }, 149 | { "SCE_KERNEL_ERROR_ILLEGAL_KTLSID" , 0x800201c0 }, 150 | { "SCE_KERNEL_ERROR_KTLS_FULL" , 0x800201c1 }, 151 | { "SCE_KERNEL_ERROR_KTLS_BUSY" , 0x800201c2 }, 152 | { "SCE_KERNEL_ERROR_PM_INVALID_PRIORITY" , 0x80020258 }, 153 | { "SCE_KERNEL_ERROR_PM_INVALID_DEVNAME" , 0x80020259 }, 154 | { "SCE_KERNEL_ERROR_PM_UNKNOWN_DEVNAME" , 0x8002025a }, 155 | { "SCE_KERNEL_ERROR_PM_PMINFO_REGISTERED" , 0x8002025b }, 156 | { "SCE_KERNEL_ERROR_PM_PMINFO_UNREGISTERED" , 0x8002025c }, 157 | { "SCE_KERNEL_ERROR_PM_INVALID_MAJOR_STATE" , 0x8002025d }, 158 | { "SCE_KERNEL_ERROR_PM_INVALID_REQUEST" , 0x8002025e }, 159 | { "SCE_KERNEL_ERROR_PM_UNKNOWN_REQUEST" , 0x8002025f }, 160 | { "SCE_KERNEL_ERROR_PM_INVALID_UNIT" , 0x80020260 }, 161 | { "SCE_KERNEL_ERROR_PM_CANNOT_CANCEL" , 0x80020261 }, 162 | { "SCE_KERNEL_ERROR_PM_INVALID_PMINFO" , 0x80020262 }, 163 | { "SCE_KERNEL_ERROR_PM_INVALID_ARGUMENT" , 0x80020263 }, 164 | { "SCE_KERNEL_ERROR_PM_ALREADY_TARGET_PWRSTATE" , 0x80020264 }, 165 | { "SCE_KERNEL_ERROR_PM_CHANGE_PWRSTATE_FAILED" , 0x80020265 }, 166 | { "SCE_KERNEL_ERROR_PM_CANNOT_CHANGE_DEVPWR_STATE" , 0x80020266 }, 167 | { "SCE_KERNEL_ERROR_PM_NO_SUPPORT_DEVPWR_STATE" , 0x80020267 }, 168 | { "SCE_KERNEL_ERROR_DMAC_REQUEST_FAILED" , 0x800202bc }, 169 | { "SCE_KERNEL_ERROR_DMAC_REQUEST_DENIED" , 0x800202bd }, 170 | { "SCE_KERNEL_ERROR_DMAC_OP_QUEUED" , 0x800202be }, 171 | { "SCE_KERNEL_ERROR_DMAC_OP_NOT_QUEUED" , 0x800202bf }, 172 | { "SCE_KERNEL_ERROR_DMAC_OP_RUNNING" , 0x800202c0 }, 173 | { "SCE_KERNEL_ERROR_DMAC_OP_NOT_ASSIGNED" , 0x800202c1 }, 174 | { "SCE_KERNEL_ERROR_DMAC_OP_TIMEOUT" , 0x800202c2 }, 175 | { "SCE_KERNEL_ERROR_DMAC_OP_FREED" , 0x800202c3 }, 176 | { "SCE_KERNEL_ERROR_DMAC_OP_USED" , 0x800202c4 }, 177 | { "SCE_KERNEL_ERROR_DMAC_OP_EMPTY" , 0x800202c5 }, 178 | { "SCE_KERNEL_ERROR_DMAC_OP_ABORTED" , 0x800202c6 }, 179 | { "SCE_KERNEL_ERROR_DMAC_OP_ERROR" , 0x800202c7 }, 180 | { "SCE_KERNEL_ERROR_DMAC_CHANNEL_RESERVED" , 0x800202c8 }, 181 | { "SCE_KERNEL_ERROR_DMAC_CHANNEL_EXCLUDED" , 0x800202c9 }, 182 | { "SCE_KERNEL_ERROR_DMAC_PRIVILEGE_ADDRESS" , 0x800202ca }, 183 | { "SCE_KERNEL_ERROR_DMAC_NO_ENOUGHSPACE" , 0x800202cb }, 184 | { "SCE_KERNEL_ERROR_DMAC_CHANNEL_NOT_ASSIGNED" , 0x800202cc }, 185 | { "SCE_KERNEL_ERROR_DMAC_CHILD_OPERATION" , 0x800202cd }, 186 | { "SCE_KERNEL_ERROR_DMAC_TOO_MUCH_SIZE" , 0x800202ce }, 187 | { "SCE_KERNEL_ERROR_DMAC_INVALID_ARGUMENT" , 0x800202cf }, 188 | { "SCE_KERNEL_ERROR_MFILE" , 0x80020320 }, 189 | { "SCE_KERNEL_ERROR_NODEV" , 0x80020321 }, 190 | { "SCE_KERNEL_ERROR_XDEV" , 0x80020322 }, 191 | { "SCE_KERNEL_ERROR_BADF" , 0x80020323 }, 192 | { "SCE_KERNEL_ERROR_INVAL" , 0x80020324 }, 193 | { "SCE_KERNEL_ERROR_UNSUP" , 0x80020325 }, 194 | { "SCE_KERNEL_ERROR_ALIAS_USED" , 0x80020326 }, 195 | { "SCE_KERNEL_ERROR_CANNOT_MOUNT" , 0x80020327 }, 196 | { "SCE_KERNEL_ERROR_DRIVER_DELETED" , 0x80020328 }, 197 | { "SCE_KERNEL_ERROR_ASYNC_BUSY" , 0x80020329 }, 198 | { "SCE_KERNEL_ERROR_NOASYNC" , 0x8002032a }, 199 | { "SCE_KERNEL_ERROR_REGDEV" , 0x8002032b }, 200 | { "SCE_KERNEL_ERROR_NOCWD" , 0x8002032c }, 201 | { "SCE_KERNEL_ERROR_NAMETOOLONG" , 0x8002032d }, 202 | { "SCE_KERNEL_ERROR_NXIO" , 0x800203e8 }, 203 | { "SCE_KERNEL_ERROR_IO" , 0x800203e9 }, 204 | { "SCE_KERNEL_ERROR_NOMEM" , 0x800203ea }, 205 | { "SCE_KERNEL_ERROR_STDIO_NOT_OPENED" , 0x800203eb }, 206 | { "SCE_KERNEL_ERROR_CACHE_ALIGNMENT" , 0x8002044c }, 207 | { "SCE_KERNEL_ERROR_ERRORMAX" , 0x8002044d }, 208 | { NULL, 0 }, 209 | }; 210 | -------------------------------------------------------------------------------- /pspkerror.h: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | * PRXTool : Utility for PSP executables. 3 | * (c) TyRaNiD 2k5 4 | * 5 | * pspkerror.h - Definitions for error codes 6 | ***************************************************************/ 7 | #ifndef PSPKERROR_H 8 | #define PSPKERROR_H 9 | 10 | #include 11 | 12 | struct PspErrorCode 13 | { 14 | const char *name; 15 | unsigned int num; 16 | }; 17 | 18 | extern struct PspErrorCode PspKernelErrorCodes[]; 19 | 20 | #endif /* PSPKERROR_H */ 21 | -------------------------------------------------------------------------------- /tinyxml/VERSION: -------------------------------------------------------------------------------- 1 | 2.3.4 2 | -------------------------------------------------------------------------------- /tinyxml/changes.txt: -------------------------------------------------------------------------------- 1 | Changes in version 1.0.1: 2 | - Fixed comment tags which were outputing as ' include. Thanks 62 | to Steve Lhomme for that. 63 | 64 | Changes in version 2.0.0 BETA 65 | - Made the ToXXX() casts safe if 'this' is null. 66 | When "LoadFile" is called with a filename, the value will correctly get set. 67 | Thanks to Brian Yoder. 68 | - Fixed bug where isalpha() and isalnum() would get called with a negative value for 69 | high ascii numbers. Thanks to Alesky Aksenov. 70 | - Fixed some errors codes that were not getting set. 71 | - Made methods "const" that were not. 72 | - Added a switch to enable or disable the ignoring of white space. ( TiXmlDocument::SetIgnoreWhiteSpace() ) 73 | - Greater standardization and code re-use in the parser. 74 | - Added a stream out operator. 75 | - Added a stream in operator. 76 | - Entity support, of predefined entites. &#x entities are untouched by input or output. 77 | - Improved text out formatting. 78 | - Fixed ReplaceChild bug, thanks to Tao Chen. 79 | 80 | Changes in version 2.0.1 81 | - Fixed hanging on loading a 0 length file. Thanks to Jeff Scozzafava. 82 | - Fixed crashing on InsertBeforeChild and InsertAfterChild. Also possibility of bad links being 83 | created by same function. Thanks to Frank De prins. 84 | - Added missing licence text. Thanks to Lars Willemsens. 85 | - Added include, at the suggestion of Steve Walters. 86 | 87 | Changes in version 2.1.0 88 | - Yves Berquin brings us the STL switch. The forum on SourceForge, and various emails to 89 | me, have long debated all out STL vs. no STL at all. And now you can have it both ways. 90 | TinyXml will compile either way. 91 | 92 | Changes in version 2.1.1 93 | - Compilation warnings. 94 | 95 | Changes in version 2.1.2 96 | - Uneeded code is not compiled in the STL case. 97 | - Changed headers so that STL can be turned on or off in tinyxml.h 98 | 99 | Changes in version 2.1.3 100 | - Fixed non-const reference in API; now uses a pointer. 101 | - Copy constructor of TiXmlString not checking for assignment to self. 102 | - Nimrod Cohen found a truly evil bug in the STL implementation that occurs 103 | when a string is converted to a c_str and then assigned to self. Search for 104 | STL_STRING_BUG for a full description. I'm asserting this is a Microsoft STL 105 | bug, since &string and string.c_str() should never be the same. Nevertheless, 106 | the code works around it. 107 | - Urivan Saaib pointed out a compiler conflict, where the C headers define 108 | the isblank macro, which was wiping out the TiXmlString::isblank() method. 109 | The method was unused and has been removed. 110 | 111 | Changes in version 2.1.4 112 | - Reworked the entity code. Entities were not correctly surving round trip input and output. 113 | Will now automatically create entities for high ascii in output. 114 | 115 | Changes in version 2.1.5 116 | - Bug fix by kylotan : infinite loop on some input (tinyxmlparser.cpp rev 1.27) 117 | - Contributed by Ivica Aracic (bytelord) : 1 new VC++ project to compile versions as static libraries (tinyxml_lib.dsp), 118 | and an example usage in xmltest.dsp 119 | (Patch request ID 678605) 120 | - A suggestion by Ronald Fenner Jr (dormlock) to add #include and for Apple's Project Builder 121 | (Patch request ID 697642) 122 | - A patch from ohommes that allows to parse correctly dots in element names and attribute names 123 | (Patch request 602600 and kylotan 701728) 124 | - A patch from hermitgeek ( James ) and wasteland for improper error reporting 125 | - Reviewed by Lee, with the following changes: 126 | - Got sick of fighting the STL/non-STL thing in the windows build. Broke 127 | them out as seperate projects. 128 | - I have too long not included the dsw. Added. 129 | - TinyXmlText had a protected Print. Odd. 130 | - Made LinkEndChild public, with docs and appropriate warnings. 131 | - Updated the docs. 132 | 133 | 2.2.0 134 | - Fixed an uninitialized pointer in the TiXmlAttributes 135 | - Fixed STL compilation problem in MinGW (and gcc 3?) - thanks Brian Yoder for finding this one 136 | - Fixed a syntax error in TiXmlDeclaration - thanks Brian Yoder 137 | - Fletcher Dunn proposed and submitted new error handling that tracked the row and column. Lee 138 | modified it to not have performance impact. 139 | - General cleanup suggestions from Fletcher Dunn. 140 | - In error handling, general errors will no longer clear the error state of specific ones. 141 | - Fix error in documentation : comments starting with " TinyXml 4 | 5 | TinyXml is a simple, small, C++ XML parser that can be easily 6 | integrating into other programs. 7 | 8 | 9 |

What it does.

10 | 11 | In brief, TinyXml parses an XML document, and builds from that a 12 | Document Object Model (DOM) that can be read, modified, and saved. 13 | 14 | XML stands for "eXtensible Markup Language." It allows you to create 15 | your own document markups. Where HTML does a very good job of marking 16 | documents for browsers, XML allows you to define any kind of document 17 | markup, for example a document that describes a "to do" list for an 18 | organizer application. XML is a very structured and convenient format. 19 | All those random file formats created to store application data can 20 | all be replaced with XML. One parser for everything. 21 | 22 | The best place for the complete, correct, and quite frankly hard to 23 | read spec is at 24 | http://www.w3.org/TR/2004/REC-xml-20040204/. An intro to XML 25 | (that I really like) can be found at 26 | http://skew.org/xml/tutorial. 27 | 28 | There are different ways to access and interact with XML data. 29 | TinyXml uses a Document Object Model (DOM), meaning the XML data is parsed 30 | into a C++ objects that can be browsed and manipulated, and then 31 | written to disk or another output stream. You can also construct an XML document from 32 | scratch with C++ objects and write this to disk or another output 33 | stream. 34 | 35 | TinyXml is designed to be easy and fast to learn. It is two headers 36 | and four cpp files. Simply add these to your project and off you go. 37 | There is an example file - xmltest.cpp - to get you started. 38 | 39 | TinyXml is released under the ZLib license, 40 | so you can use it in open source or commercial code. The details 41 | of the license are at the top of every source file. 42 | 43 | TinyXml attempts to be a flexible parser, but with truly correct and 44 | compliant XML output. TinyXml should compile on any reasonably C++ 45 | compliant system. It does not rely on exceptions or RTTI. It can be 46 | compiled with or without STL support. TinyXml fully supports 47 | the UTF-8 encoding, and the first 64k character entities. 48 | 49 | 50 |

What it doesn't do.

51 | 52 | It doesnt parse or use DTDs (Document Type Definitions) or XSLs 53 | (eXtensible Stylesheet Language.) There are other parsers out there 54 | (check out www.sourceforge.org, search for XML) that are much more fully 55 | featured. But they are also much bigger, take longer to set up in 56 | your project, have a higher learning curve, and often have a more 57 | restrictive license. If you are working with browsers or have more 58 | complete XML needs, TinyXml is not the parser for you. 59 | 60 | The following DTD syntax will not parse at this time in TinyXml: 61 | 62 | @verbatim 63 | 65 | ]> 66 | @endverbatim 67 | 68 | because TinyXml sees this as a !DOCTYPE node with an illegally 69 | embedded !ELEMENT node. This may be addressed in the future. 70 | 71 |

Code Status.

72 | 73 | TinyXml is mature, tested code. It is very stable. If you find 74 | bugs, please file a bug report is on the sourceforge web site 75 | (www.sourceforge.net/projects/tinyxml). 76 | We'll get them straightened out as soon as possible. 77 | 78 | There are some areas of improvement; please check sourceforge if you are 79 | interested in working on TinyXml. 80 | 81 | 82 |

Features

83 | 84 |

Using STL

85 | 86 | TinyXml can be compiled to use or not use STL. When using STL, TinyXml 87 | uses the std::string class, and fully supports std::istream, std::ostream, 88 | operator<<, and operator>>. Many API methods have both 'const char*' and 89 | 'const std::string&' forms. 90 | 91 | When STL support is compiled out, no STL files are included whatsover. All 92 | the string classes are implemented by TinyXml itself. API methods 93 | all use the 'const char*' form for input. 94 | 95 | Use the compile time #define: 96 | 97 | TIXML_USE_STL 98 | 99 | to compile one version or the other. This can be passed by the compiler, 100 | or set as the first line of "tinyxml.h". 101 | 102 | Note: If compiling the test code in Linux, setting the environment 103 | variable TINYXML_USE_STL=YES/NO will control STL compilation. In the 104 | Windows project file, STL and non STL targets are provided. In your project, 105 | its probably easiest to add the line "#define TIXML_USE_STL" as the first 106 | line of tinyxml.h. 107 | 108 |

UTF-8

109 | 110 | TinyXml supports UTF-8 allowing to manipulate XML files in any language. TinyXml 111 | also supports "legacy mode" - the encoding used before UTF-8 support and 112 | probably best described as "extended ascii". 113 | 114 | Normally, TinyXml will try to detect the correct encoding and use it. However, 115 | by setting the value of TIXML_DEFAULT_ENCODING in the header file, TinyXml 116 | can be forced to always use one encoding. 117 | 118 | TinyXml will assume Legacy Mode until one of the following occurs: 119 |
    120 |
  1. If the non-standard but common "UTF-8 lead bytes" (0xef 0xbb 0xbf) 121 | begin the file or data stream, TinyXml will read it as UTF-8.
  2. 122 |
  3. If the declaration tag is read, and it has an encoding="UTF-8", then 123 | TinyXml will read it as UTF-8.
  4. 124 |
  5. If the declaration tag is read, and it has no encoding specified, then 125 | TinyXml will read it as UTF-8.
  6. 126 |
  7. If the declaration tag is read, and it has an encoding="something else", then 127 | TinyXml will read it as Legacy Mode. In legacy mode, TinyXml will 128 | work as it did before. It's not clear what that mode does exactly, but 129 | old content should keep working.
  8. 130 |
  9. Until one of the above criteria is met, TinyXml runs in Legacy Mode.
  10. 131 |
132 | 133 | What happens if the encoding is incorrectly set or detected? TinyXml will try 134 | to read and pass through text seen as improperly encoded. You may get some strange 135 | results or mangled characters. You may want to force TinyXml to the correct mode. 136 | 137 | You may force TinyXml to Legacy Mode by using LoadFile( TIXML_ENCODING_LEGACY ) or 138 | LoadFile( filename, TIXML_ENCODING_LEGACY ). You may force it to use legacy mode all 139 | the time by setting TIXML_DEFAULT_ENCODING = TIXML_ENCODING_LEGACY. Likewise, you may 140 | force it to TIXML_ENCODING_UTF8 with the same technique. 141 | 142 | For English users, using English XML, UTF-8 is the same as low-ASCII. You 143 | don't need to be aware of UTF-8 or change your code in any way. You can think 144 | of UTF-8 as a "superset" of ASCII. 145 | 146 | UTF-8 is not a double byte format - but it is a standard encoding of Unicode! 147 | TinyXml does not use or directly support wchar, TCHAR, or Microsofts _UNICODE at this time. 148 | It is common to see the term "Unicode" improperly refer to UTF-16, a wide byte encoding 149 | of unicode. This is a source of confusion. 150 | 151 | For "high-ascii" languages - everything not English, pretty much - TinyXml can 152 | handle all languages, at the same time, as long as the XML is encoded 153 | in UTF-8. That can be a little tricky, older programs and operating systems 154 | tend to use the "default" or "traditional" code page. Many apps (and almost all 155 | modern ones) can output UTF-8, but older or stubborn (or just broken) ones 156 | still output text in the default code page. 157 | 158 | For example, Japanese systems traditionally use SHIFT-JIS encoding. 159 | Text encoded as SHIFT-JIS can not be read by tinyxml. 160 | A good text editor can import SHIFT-JIS and then save as UTF-8. 161 | 162 | The Skew.org link does a great 163 | job covering the encoding issue. 164 | 165 | The test file "utf8test.xml" is an XML containing English, Spanish, Russian, 166 | and Simplified Chinese. (Hopefully they are translated correctly). The file 167 | "utf8test.gif" is a screen capture of the XML file, rendered in IE. Note that 168 | if you don't have the correct fonts (Simplified Chinese or Russian) on your 169 | system, you won't see output that matches the GIF file even if you can parse 170 | it correctly. Also note that (at least on my Windows machine) console output 171 | is in a Western code page, so that Print() or printf() cannot correctly display 172 | the file. This is not a bug in TinyXml - just an OS issue. No data is lost or 173 | destroyed by TinyXml. The console just doesn't render UTF-8. 174 | 175 | 176 |

Entities

177 | TinyXml recognizes the pre-defined "character entities", meaning special 178 | characters. Namely: 179 | 180 | @verbatim 181 | & & 182 | < < 183 | > > 184 | " " 185 | ' ' 186 | @endverbatim 187 | 188 | These are recognized when the XML document is read, and translated to there 189 | UTF-8 equivalents. For instance, text with the XML of: 190 | 191 | @verbatim 192 | Far & Away 193 | @endverbatim 194 | 195 | will have the Value() of "Far & Away" when queried from the TiXmlText object, 196 | and will be written back to the XML stream/file as an ampersand. Older versions 197 | of TinyXml "preserved" character entities, but the newer versions will translate 198 | them into characters. 199 | 200 | Additionally, any character can be specified by its Unicode code point: 201 | The syntax " " or " " are both to the non-breaking space characher. 202 | 203 | 204 |

Streams

205 | With TIXML_USE_STL on, 206 | TiXml has been modified to support both C (FILE) and C++ (operator <<,>>) 207 | streams. There are some differences that you may need to be aware of. 208 | 209 | C style output: 210 | - based on FILE* 211 | - the Print() and SaveFile() methods 212 | 213 | Generates formatted output, with plenty of white space, intended to be as 214 | human-readable as possible. They are very fast, and tolerant of ill formed 215 | XML documents. For example, an XML document that contains 2 root elements 216 | and 2 declarations, will still print. 217 | 218 | C style input: 219 | - based on FILE* 220 | - the Parse() and LoadFile() methods 221 | 222 | A fast, tolerant read. Use whenever you don't need the C++ streams. 223 | 224 | C++ style ouput: 225 | - based on std::ostream 226 | - operator<< 227 | 228 | Generates condensed output, intended for network transmission rather than 229 | readability. Depending on your system's implementation of the ostream class, 230 | these may be somewhat slower. (Or may not.) Not tolerant of ill formed XML: 231 | a document should contain the correct one root element. Additional root level 232 | elements will not be streamed out. 233 | 234 | C++ style input: 235 | - based on std::istream 236 | - operator>> 237 | 238 | Reads XML from a stream, making it useful for network transmission. The tricky 239 | part is knowing when the XML document is complete, since there will almost 240 | certainly be other data in the stream. TinyXml will assume the XML data is 241 | complete after it reads the root element. Put another way, documents that 242 | are ill-constructed with more than one root element will not read correctly. 243 | Also note that operator>> is somewhat slower than Parse, due to both 244 | implementation of the STL and limitations of TinyXml. 245 | 246 |

White space

247 | The world simply does not agree on whether white space should be kept, or condensed. 248 | For example, pretend the '_' is a space, and look at "Hello____world". HTML, and 249 | at least some XML parsers, will interpret this as "Hello_world". They condense white 250 | space. Some XML parsers do not, and will leave it as "Hello____world". (Remember 251 | to keep pretending the _ is a space.) Others suggest that __Hello___world__ should become 252 | Hello___world. 253 | 254 | It's an issue that hasn't been resolved to my satisfaction. TinyXml supports the 255 | first 2 approaches. Call TiXmlBase::SetCondenseWhiteSpace( bool ) to set the desired behavior. 256 | The default is to condense white space. 257 | 258 | If you change the default, you should call TiXmlBase::SetCondenseWhiteSpace( bool ) 259 | before making any calls to Parse XML data, and I don't recommend changing it after 260 | it has been set. 261 | 262 | 263 |

Handles

264 | 265 | Where browsing an XML document in a robust way, it is important to check 266 | for null returns from method calls. An error safe implementation can 267 | generate a lot of code like: 268 | 269 | @verbatim 270 | TiXmlElement* root = document.FirstChildElement( "Document" ); 271 | if ( root ) 272 | { 273 | TiXmlElement* element = root->FirstChildElement( "Element" ); 274 | if ( element ) 275 | { 276 | TiXmlElement* child = element->FirstChildElement( "Child" ); 277 | if ( child ) 278 | { 279 | TiXmlElement* child2 = child->NextSiblingElement( "Child" ); 280 | if ( child2 ) 281 | { 282 | // Finally do something useful. 283 | @endverbatim 284 | 285 | Handles have been introduced to clean this up. Using the TiXmlHandle class, 286 | the previous code reduces to: 287 | 288 | @verbatim 289 | TiXmlHandle docHandle( &document ); 290 | TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).Element(); 291 | if ( child2 ) 292 | { 293 | // do something useful 294 | @endverbatim 295 | 296 | Which is much easier to deal with. See TiXmlHandle for more information. 297 | 298 | 299 |

Row and Column tracking

300 | Being able to track nodes and attributes back to their origin location 301 | in source files can be very important for some applications. Additionally, 302 | knowing where parsing errors occured in the original source can be very 303 | time saving. 304 | 305 | TinyXml can tracks the row and column origin of all nodes and attributes 306 | in a text file. The TiXmlBase::Row() and TiXmlBase::Column() methods return 307 | the origin of the node in the source text. The correct tabs can be 308 | configured in TiXmlDocument::SetTabSize(). 309 | 310 | 311 |

Using and Installing

312 | 313 | To Compile and Run xmltest: 314 | 315 | A Linux Makefile and a Windows Visual C++ .dsw file is provided. 316 | Simply compile and run. It will write the file demotest.xml to your 317 | disk and generate output on the screen. It also tests walking the 318 | DOM by printing out the number of nodes found using different 319 | techniques. 320 | 321 | The Linux makefile is very generic and will 322 | probably run on other systems, but is only tested on Linux. You no 323 | longer need to run 'make depend'. The dependecies have been 324 | hard coded. 325 | 326 |

Windows project file for VC6

327 |
    328 |
  • tinyxml: tinyxml library, non-STL
  • 329 |
  • tinyxmlSTL: tinyxml library, STL
  • 330 |
  • tinyXmlTest: test app, non-STL
  • 331 |
  • tinyXmlTestSTL: test app, STL
  • 332 |
333 | 334 |

Linux Make file

335 | At the top of the makefile you can set: 336 | 337 | PROFILE, DEBUG, and TINYXML_USE_STL. Details (such that they are) are in 338 | the makefile. 339 | 340 | In the tinyxml directory, type "make clean" then "make". The executable 341 | file 'xmltest' will be created. 342 | 343 | 344 | 345 |

To Use in an Application:

346 | 347 | Add tinyxml.cpp, tinyxml.h, tinyxmlerror.cpp, tinyxmlparser.cpp, tinystr.cpp, and tinystr.h to your 348 | project or make file. That's it! It should compile on any reasonably 349 | compliant C++ system. You do not need to enable exceptions or 350 | RTTI for TinyXml. 351 | 352 | 353 |

How TinyXml works.

354 | 355 | An example is probably the best way to go. Take: 356 | @verbatim 357 | 358 | 359 | 360 | Go to the Toy store! 361 | Do bills 362 | 363 | @endverbatim 364 | 365 | Its not much of a To Do list, but it will do. To read this file 366 | (say "demo.xml") you would create a document, and parse it in: 367 | @verbatim 368 | TiXmlDocument doc( "demo.xml" ); 369 | doc.LoadFile(); 370 | @endverbatim 371 | 372 | And its ready to go. Now lets look at some lines and how they 373 | relate to the DOM. 374 | 375 | @verbatim 376 | 377 | @endverbatim 378 | 379 | The first line is a declaration, and gets turned into the 380 | TiXmlDeclaration class. It will be the first child of the 381 | document node. 382 | 383 | This is the only directive/special tag parsed by by TinyXml. 384 | Generally directive targs are stored in TiXmlUnknown so the 385 | commands wont be lost when it is saved back to disk. 386 | 387 | @verbatim 388 | 389 | @endverbatim 390 | 391 | A comment. Will become a TiXmlComment object. 392 | 393 | @verbatim 394 | 395 | @endverbatim 396 | 397 | The "ToDo" tag defines a TiXmlElement object. This one does not have 398 | any attributes, but does contain 2 other elements. 399 | 400 | @verbatim 401 | 402 | @endverbatim 403 | 404 | Creates another TiXmlElement which is a child of the "ToDo" element. 405 | This element has 1 attribute, with the name "priority" and the value 406 | "1". 407 | 408 | Go to the 409 | 410 | A TiXmlText. This is a leaf node and cannot contain other nodes. 411 | It is a child of the "Item" TiXmlElement. 412 | 413 | @verbatim 414 | 415 | @endverbatim 416 | 417 | 418 | Another TiXmlElement, this one a child of the "Item" element. 419 | 420 | Etc. 421 | 422 | Looking at the entire object tree, you end up with: 423 | @verbatim 424 | TiXmlDocument "demo.xml" 425 | TiXmlDeclaration "version='1.0'" "standalone=no" 426 | TiXmlComment " Our to do list data" 427 | TiXmlElement "ToDo" 428 | TiXmlElement "Item" Attribtutes: priority = 1 429 | TiXmlText "Go to the " 430 | TiXmlElement "bold" 431 | TiXmlText "Toy store!" 432 | TiXmlElement "Item" Attributes: priority=2 433 | TiXmlText "Do bills" 434 | @endverbatim 435 | 436 |

Documentation

437 | 438 | The documentation is build with Doxygen, using the 'dox' 439 | configuration file. 440 | 441 |

License

442 | 443 | TinyXml is released under the zlib license: 444 | 445 | This software is provided 'as-is', without any express or implied 446 | warranty. In no event will the authors be held liable for any 447 | damages arising from the use of this software. 448 | 449 | Permission is granted to anyone to use this software for any 450 | purpose, including commercial applications, and to alter it and 451 | redistribute it freely, subject to the following restrictions: 452 | 453 | 1. The origin of this software must not be misrepresented; you must 454 | not claim that you wrote the original software. If you use this 455 | software in a product, an acknowledgment in the product documentation 456 | would be appreciated but is not required. 457 | 458 | 2. Altered source versions must be plainly marked as such, and 459 | must not be misrepresented as being the original software. 460 | 461 | 3. This notice may not be removed or altered from any source 462 | distribution. 463 | 464 |

References

465 | 466 | The World Wide Web Consortium is the definitive standard body for 467 | XML, and there web pages contain huge amounts of information. 468 | 469 | The definitive spec: 470 | http://www.w3.org/TR/2004/REC-xml-20040204/ 471 | 472 | I also recommend "XML Pocket Reference" by Robert Eckstein and published by 473 | OReilly...the book that got the whole thing started. 474 | 475 |

Contributors, Contacts, and a Brief History

476 | 477 | Thanks very much to everyone who sends suggestions, bugs, ideas, and 478 | encouragement. It all helps, and makes this project fun. A special thanks 479 | to the contributors on the web pages that keep it lively. 480 | 481 | So many people have sent in bugs and ideas, that rather than list here 482 | we try to give credit due in the "changes.txt" file. 483 | 484 | TinyXml was originally written be Lee Thomason. (Often the "I" still 485 | in the documenation.) Lee reviews changes and releases new versions, 486 | with the help of Yves Berquin and the tinyXml community. 487 | 488 | We appreciate your suggestions, and would love to know if you 489 | use TinyXml. Hopefully you will enjoy it and find it useful. 490 | Please post questions, comments, file bugs, or contact us at: 491 | 492 | www.sourceforge.net/projects/tinyxml 493 | 494 | Lee Thomason, 495 | Yves Berquin 496 | */ 497 | -------------------------------------------------------------------------------- /tinyxml/tinystr.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | www.sourceforge.net/projects/tinyxml 3 | Original file by Yves Berquin. 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any 7 | damages arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any 10 | purpose, including commercial applications, and to alter it and 11 | redistribute it freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must 14 | not claim that you wrote the original software. If you use this 15 | software in a product, an acknowledgment in the product documentation 16 | would be appreciated but is not required. 17 | 18 | 2. Altered source versions must be plainly marked as such, and 19 | must not be misrepresented as being the original software. 20 | 21 | 3. This notice may not be removed or altered from any source 22 | distribution. 23 | */ 24 | 25 | #include "tinyxml.h" 26 | 27 | #ifndef TIXML_USE_STL 28 | 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | #include "tinystr.h" 35 | 36 | // TiXmlString constructor, based on a C string 37 | TiXmlString::TiXmlString (const char* instring) 38 | { 39 | size_t newlen; 40 | char * newstring; 41 | 42 | if (!instring) 43 | { 44 | allocated = 0; 45 | cstring = NULL; 46 | current_length = 0; 47 | return; 48 | } 49 | newlen = strlen (instring) + 1; 50 | newstring = new char [newlen]; 51 | memcpy (newstring, instring, newlen); 52 | // strcpy (newstring, instring); 53 | allocated = newlen; 54 | cstring = newstring; 55 | current_length = newlen - 1; 56 | } 57 | 58 | // TiXmlString copy constructor 59 | TiXmlString::TiXmlString (const TiXmlString& copy) 60 | { 61 | size_t newlen; 62 | char * newstring; 63 | 64 | // Prevent copy to self! 65 | if ( © == this ) 66 | return; 67 | 68 | if (! copy . allocated) 69 | { 70 | allocated = 0; 71 | cstring = NULL; 72 | current_length = 0; 73 | return; 74 | } 75 | newlen = copy . length () + 1; 76 | newstring = new char [newlen]; 77 | // strcpy (newstring, copy . cstring); 78 | memcpy (newstring, copy . cstring, newlen); 79 | allocated = newlen; 80 | cstring = newstring; 81 | current_length = newlen - 1; 82 | } 83 | 84 | // TiXmlString = operator. Safe when assign own content 85 | void TiXmlString ::operator = (const char * content) 86 | { 87 | size_t newlen; 88 | char * newstring; 89 | 90 | if (! content) 91 | { 92 | empty_it (); 93 | return; 94 | } 95 | newlen = strlen (content) + 1; 96 | newstring = new char [newlen]; 97 | // strcpy (newstring, content); 98 | memcpy (newstring, content, newlen); 99 | empty_it (); 100 | allocated = newlen; 101 | cstring = newstring; 102 | current_length = newlen - 1; 103 | } 104 | 105 | // = operator. Safe when assign own content 106 | void TiXmlString ::operator = (const TiXmlString & copy) 107 | { 108 | size_t newlen; 109 | char * newstring; 110 | 111 | if (! copy . length ()) 112 | { 113 | empty_it (); 114 | return; 115 | } 116 | newlen = copy . length () + 1; 117 | newstring = new char [newlen]; 118 | // strcpy (newstring, copy . c_str ()); 119 | memcpy (newstring, copy . c_str (), newlen); 120 | empty_it (); 121 | allocated = newlen; 122 | cstring = newstring; 123 | current_length = newlen - 1; 124 | } 125 | 126 | 127 | // append a const char * to an existing TiXmlString 128 | void TiXmlString::append( const char* str, size_t len ) 129 | { 130 | char * new_string; 131 | size_t new_alloc, new_size, size_suffix; 132 | 133 | // don't use strlen - it can overrun the len passed in! 134 | const char* p = str; 135 | size_suffix = 0; 136 | 137 | while ( *p && size_suffix < (unsigned)len ) 138 | { 139 | ++p; 140 | ++size_suffix; 141 | } 142 | if ( !size_suffix) 143 | return; 144 | 145 | new_size = length () + size_suffix + 1; 146 | // check if we need to expand 147 | if (new_size > allocated) 148 | { 149 | // compute new size 150 | new_alloc = assign_new_size (new_size); 151 | 152 | // allocate new buffer 153 | new_string = new char [new_alloc]; 154 | new_string [0] = 0; 155 | 156 | // copy the previous allocated buffer into this one 157 | if (allocated && cstring) 158 | // strcpy (new_string, cstring); 159 | memcpy (new_string, cstring, length ()); 160 | 161 | // append the suffix. It does exist, otherwize we wouldn't be expanding 162 | // strncat (new_string, str, len); 163 | memcpy (new_string + length (), 164 | str, 165 | size_suffix); 166 | 167 | // return previsously allocated buffer if any 168 | if (allocated && cstring) 169 | delete [] cstring; 170 | 171 | // update member variables 172 | cstring = new_string; 173 | allocated = new_alloc; 174 | } 175 | else 176 | { 177 | // we know we can safely append the new string 178 | // strncat (cstring, str, len); 179 | memcpy (cstring + length (), 180 | str, 181 | size_suffix); 182 | } 183 | current_length = new_size - 1; 184 | cstring [current_length] = 0; 185 | } 186 | 187 | 188 | // append a const char * to an existing TiXmlString 189 | void TiXmlString::append( const char * suffix ) 190 | { 191 | char * new_string; 192 | size_t new_alloc, new_size; 193 | 194 | new_size = length () + strlen (suffix) + 1; 195 | // check if we need to expand 196 | if (new_size > allocated) 197 | { 198 | // compute new size 199 | new_alloc = assign_new_size (new_size); 200 | 201 | // allocate new buffer 202 | new_string = new char [new_alloc]; 203 | new_string [0] = 0; 204 | 205 | // copy the previous allocated buffer into this one 206 | if (allocated && cstring) 207 | memcpy (new_string, cstring, 1 + length ()); 208 | // strcpy (new_string, cstring); 209 | 210 | // append the suffix. It does exist, otherwize we wouldn't be expanding 211 | // strcat (new_string, suffix); 212 | memcpy (new_string + length (), 213 | suffix, 214 | strlen (suffix) + 1); 215 | 216 | // return previsously allocated buffer if any 217 | if (allocated && cstring) 218 | delete [] cstring; 219 | 220 | // update member variables 221 | cstring = new_string; 222 | allocated = new_alloc; 223 | } 224 | else 225 | { 226 | // we know we can safely append the new string 227 | // strcat (cstring, suffix); 228 | memcpy (cstring + length (), 229 | suffix, 230 | strlen (suffix) + 1); 231 | } 232 | current_length = new_size - 1; 233 | } 234 | 235 | // Check for TiXmlString equuivalence 236 | //bool TiXmlString::operator == (const TiXmlString & compare) const 237 | //{ 238 | // return (! strcmp (c_str (), compare . c_str ())); 239 | //} 240 | 241 | //unsigned TiXmlString::length () const 242 | //{ 243 | // if (allocated) 244 | // // return strlen (cstring); 245 | // return current_length; 246 | // return 0; 247 | //} 248 | 249 | 250 | unsigned TiXmlString::find (char tofind, unsigned offset) const 251 | { 252 | char * lookup; 253 | 254 | if (offset >= length ()) 255 | return (unsigned) notfound; 256 | for (lookup = cstring + offset; * lookup; lookup++) 257 | if (* lookup == tofind) 258 | return (unsigned)(lookup - cstring); 259 | return (unsigned) notfound; 260 | } 261 | 262 | 263 | bool TiXmlString::operator == (const TiXmlString & compare) const 264 | { 265 | if ( allocated && compare.allocated ) 266 | { 267 | assert( cstring ); 268 | assert( compare.cstring ); 269 | return ( strcmp( cstring, compare.cstring ) == 0 ); 270 | } 271 | else if ( length() == 0 && compare.length() == 0 ) 272 | { 273 | return true; 274 | } 275 | return false; 276 | } 277 | 278 | 279 | bool TiXmlString::operator == (const char* compare) const 280 | { 281 | if ( allocated && compare && *compare ) 282 | { 283 | assert( cstring ); 284 | return ( strcmp( cstring, compare ) == 0 ); 285 | } 286 | else if ( length() == 0 && (!compare || !*compare ) ) // this is a little dubious, but try to duplicate behavior in other operator== 287 | { 288 | return true; 289 | } 290 | return false; 291 | } 292 | 293 | 294 | bool TiXmlString::operator < (const TiXmlString & compare) const 295 | { 296 | if ( allocated && compare.allocated ) 297 | { 298 | assert( cstring ); 299 | assert( compare.cstring ); 300 | return ( strcmp( cstring, compare.cstring ) > 0 ); 301 | } 302 | return false; 303 | } 304 | 305 | 306 | bool TiXmlString::operator > (const TiXmlString & compare) const 307 | { 308 | if ( allocated && compare.allocated ) 309 | { 310 | assert( cstring ); 311 | assert( compare.cstring ); 312 | return ( strcmp( cstring, compare.cstring ) < 0 ); 313 | } 314 | return false; 315 | } 316 | 317 | 318 | #endif // TIXML_USE_STL 319 | -------------------------------------------------------------------------------- /tinyxml/tinystr.h: -------------------------------------------------------------------------------- 1 | /* 2 | www.sourceforge.net/projects/tinyxml 3 | Original file by Yves Berquin. 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any 7 | damages arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any 10 | purpose, including commercial applications, and to alter it and 11 | redistribute it freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must 14 | not claim that you wrote the original software. If you use this 15 | software in a product, an acknowledgment in the product documentation 16 | would be appreciated but is not required. 17 | 18 | 2. Altered source versions must be plainly marked as such, and 19 | must not be misrepresented as being the original software. 20 | 21 | 3. This notice may not be removed or altered from any source 22 | distribution. 23 | */ 24 | 25 | #include "tinyxml.h" 26 | 27 | 28 | #ifndef TIXML_USE_STL 29 | 30 | #ifndef TIXML_STRING_INCLUDED 31 | #define TIXML_STRING_INCLUDED 32 | 33 | #ifdef _MSC_VER 34 | #pragma warning( disable : 4530 ) 35 | #pragma warning( disable : 4786 ) 36 | #endif 37 | 38 | #include 39 | 40 | /* 41 | TiXmlString is an emulation of the std::string template. 42 | Its purpose is to allow compiling TinyXML on compilers with no or poor STL support. 43 | Only the member functions relevant to the TinyXML project have been implemented. 44 | The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase 45 | a string and there's no more room, we allocate a buffer twice as big as we need. 46 | */ 47 | class TiXmlString 48 | { 49 | public : 50 | // TiXmlString constructor, based on a string, mark explicit to force 51 | // us to find unnecessary casting. 52 | explicit TiXmlString (const char * instring); 53 | 54 | // TiXmlString empty constructor 55 | TiXmlString () 56 | { 57 | allocated = 0; 58 | cstring = NULL; 59 | current_length = 0; 60 | } 61 | 62 | // TiXmlString copy constructor 63 | explicit TiXmlString (const TiXmlString& copy); 64 | 65 | // TiXmlString destructor 66 | ~ TiXmlString () 67 | { 68 | empty_it (); 69 | } 70 | 71 | // Convert a TiXmlString into a classical char * 72 | const char * c_str () const 73 | { 74 | if (allocated) 75 | return cstring; 76 | return ""; 77 | } 78 | 79 | // Return the length of a TiXmlString 80 | size_t length () const 81 | { 82 | return ( allocated ) ? current_length : 0; 83 | } 84 | 85 | // TiXmlString = operator 86 | void operator = (const char * content); 87 | 88 | // = operator 89 | void operator = (const TiXmlString & copy); 90 | 91 | // += operator. Maps to append 92 | TiXmlString& operator += (const char * suffix) 93 | { 94 | append (suffix); 95 | return *this; 96 | } 97 | 98 | // += operator. Maps to append 99 | TiXmlString& operator += (char single) 100 | { 101 | append (single); 102 | return *this; 103 | } 104 | 105 | // += operator. Maps to append 106 | TiXmlString& operator += (TiXmlString & suffix) 107 | { 108 | append (suffix); 109 | return *this; 110 | } 111 | bool operator == (const TiXmlString & compare) const; 112 | bool operator == (const char* compare) const; 113 | bool operator < (const TiXmlString & compare) const; 114 | bool operator > (const TiXmlString & compare) const; 115 | 116 | // Checks if a TiXmlString is empty 117 | bool empty () const 118 | { 119 | return length () ? false : true; 120 | } 121 | 122 | // single char extraction 123 | const char& at (unsigned index) const 124 | { 125 | assert( index < length ()); 126 | return cstring [index]; 127 | } 128 | 129 | // find a char in a string. Return TiXmlString::notfound if not found 130 | unsigned find (char lookup) const 131 | { 132 | return find (lookup, 0); 133 | } 134 | 135 | // find a char in a string from an offset. Return TiXmlString::notfound if not found 136 | unsigned find (char tofind, unsigned offset) const; 137 | 138 | /* Function to reserve a big amount of data when we know we'll need it. Be aware that this 139 | function clears the content of the TiXmlString if any exists. 140 | */ 141 | void reserve (unsigned size) 142 | { 143 | empty_it (); 144 | if (size) 145 | { 146 | allocated = size; 147 | cstring = new char [size]; 148 | cstring [0] = 0; 149 | current_length = 0; 150 | } 151 | } 152 | 153 | // [] operator 154 | char& operator [] (unsigned index) const 155 | { 156 | assert( index < length ()); 157 | return cstring [index]; 158 | } 159 | 160 | // Error value for find primitive 161 | enum { notfound = 0xffffffff, 162 | npos = notfound }; 163 | 164 | void append (const char *str, size_t len ); 165 | 166 | protected : 167 | 168 | // The base string 169 | char * cstring; 170 | // Number of chars allocated 171 | size_t allocated; 172 | // Current string size 173 | size_t current_length; 174 | 175 | // New size computation. It is simplistic right now : it returns twice the amount 176 | // we need 177 | size_t assign_new_size (size_t minimum_to_allocate) 178 | { 179 | return minimum_to_allocate * 2; 180 | } 181 | 182 | // Internal function that clears the content of a TiXmlString 183 | void empty_it () 184 | { 185 | if (cstring) 186 | delete [] cstring; 187 | cstring = NULL; 188 | allocated = 0; 189 | current_length = 0; 190 | } 191 | 192 | void append (const char *suffix ); 193 | 194 | // append function for another TiXmlString 195 | void append (const TiXmlString & suffix) 196 | { 197 | append (suffix . c_str ()); 198 | } 199 | 200 | // append for a single char. 201 | void append (char single) 202 | { 203 | if ( cstring && current_length < (allocated-1) ) 204 | { 205 | cstring[ current_length ] = single; 206 | ++current_length; 207 | cstring[ current_length ] = 0; 208 | } 209 | else 210 | { 211 | char smallstr [2]; 212 | smallstr [0] = single; 213 | smallstr [1] = 0; 214 | append (smallstr); 215 | } 216 | } 217 | 218 | } ; 219 | 220 | /* 221 | TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString. 222 | Only the operators that we need for TinyXML have been developped. 223 | */ 224 | class TiXmlOutStream : public TiXmlString 225 | { 226 | public : 227 | TiXmlOutStream () : TiXmlString () {} 228 | 229 | // TiXmlOutStream << operator. Maps to TiXmlString::append 230 | TiXmlOutStream & operator << (const char * in) 231 | { 232 | append (in); 233 | return (* this); 234 | } 235 | 236 | // TiXmlOutStream << operator. Maps to TiXmlString::append 237 | TiXmlOutStream & operator << (const TiXmlString & in) 238 | { 239 | append (in . c_str ()); 240 | return (* this); 241 | } 242 | } ; 243 | 244 | #ifdef _MSC_VER 245 | #pragma warning( default : 4530 ) 246 | #pragma warning( default : 4786 ) 247 | #endif 248 | 249 | #endif // TIXML_STRING_INCLUDED 250 | #endif // TIXML_USE_STL 251 | -------------------------------------------------------------------------------- /tinyxml/tinyxmlerror.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | www.sourceforge.net/projects/tinyxml 3 | Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com) 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any 7 | damages arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any 10 | purpose, including commercial applications, and to alter it and 11 | redistribute it freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must 14 | not claim that you wrote the original software. If you use this 15 | software in a product, an acknowledgment in the product documentation 16 | would be appreciated but is not required. 17 | 18 | 2. Altered source versions must be plainly marked as such, and 19 | must not be misrepresented as being the original software. 20 | 21 | 3. This notice may not be removed or altered from any source 22 | distribution. 23 | */ 24 | 25 | #include "tinyxml.h" 26 | 27 | // The goal of the seperate error file is to make the first 28 | // step towards localization. tinyxml (currently) only supports 29 | // latin-1, but at least the error messages could now be translated. 30 | // 31 | // It also cleans up the code a bit. 32 | // 33 | 34 | const char* TiXmlBase::errorString[ TIXML_ERROR_STRING_COUNT ] = 35 | { 36 | "No error", 37 | "Error", 38 | "Failed to open file", 39 | "Memory allocation failed.", 40 | "Error parsing Element.", 41 | "Failed to read Element name", 42 | "Error reading Element value.", 43 | "Error reading Attributes.", 44 | "Error: empty tag.", 45 | "Error reading end tag.", 46 | "Error parsing Unknown.", 47 | "Error parsing Comment.", 48 | "Error parsing Declaration.", 49 | "Error document empty.", 50 | "Error null (0) or unexpected EOF found in input stream.", 51 | }; 52 | -------------------------------------------------------------------------------- /types.h: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | * PRXTool : Utility for PSP executables. 3 | * (c) TyRaNiD 2k5 4 | * 5 | * types.h - Definition of basic cross platform types. 6 | ***************************************************************/ 7 | 8 | #ifndef __TYPES_H__ 9 | #define __TYPES_H__ 10 | 11 | #ifdef HAVE_CONFIG_H 12 | #include "config.h" 13 | #include "_stdint.h" 14 | #else 15 | #include 16 | #define uint8_t u_int8_t 17 | #define uint16_t u_int16_t 18 | #define uint32_t u_int32_t 19 | #define uint64_t u_int64_t 20 | #endif 21 | 22 | /* Re-define some system types */ 23 | typedef uint8_t u8; 24 | typedef uint16_t u16; 25 | typedef uint32_t u32; 26 | typedef uint64_t u64; 27 | typedef int8_t s8; 28 | typedef int16_t s16; 29 | typedef int32_t s32; 30 | typedef int64_t s64; 31 | 32 | #ifdef WORDS_BIGENDIAN 33 | inline u32 lw_le(u32 data) 34 | { 35 | u8 *ptr; 36 | u32 val; 37 | 38 | ptr = (u8*) &data; 39 | 40 | val = ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24); 41 | 42 | return val; 43 | } 44 | 45 | inline u16 lh_le(u16 data) 46 | { 47 | u8 *ptr; 48 | u16 val; 49 | 50 | ptr = (u8*) &data; 51 | 52 | val = ptr[0] | (ptr[1] << 8); 53 | 54 | return val; 55 | } 56 | 57 | #define LW_LE(x) (lw_le((x))) 58 | #define LW_BE(x) (x) 59 | #define LH_LE(x) (lh_le((x))) 60 | #define LH_BE(x) (x) 61 | 62 | #else 63 | 64 | inline u32 lw_be(u32 data) 65 | { 66 | u8 *ptr; 67 | u32 val; 68 | 69 | ptr = (u8*) &data; 70 | 71 | val = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3]; 72 | 73 | return val; 74 | } 75 | 76 | inline u16 lh_be(u16 data) 77 | { 78 | u8 *ptr; 79 | u16 val; 80 | 81 | ptr = (u8*) &data; 82 | 83 | val = (ptr[0] << 16) | ptr[1]; 84 | 85 | return val; 86 | } 87 | 88 | #define LW_LE(x) (x) 89 | #define LW_BE(x) (lw_be((x))) 90 | #define LH_LE(x) (x) 91 | #define LH_BE(x) (lh_be((x))) 92 | 93 | #endif 94 | 95 | #define LW(x) (LW_LE(x)) 96 | #define LH(x) (LH_LE(x)) 97 | 98 | 99 | #ifdef WORDS_BIGENDIAN 100 | inline void sw_le(u32 *data, u32 val) 101 | { 102 | u8* ptr = (u8*) data; 103 | 104 | ptr[0] = (u8) (val & 0xFF); 105 | ptr[1] = (u8) ((val >> 8) & 0xFF); 106 | ptr[2] = (u8) ((val >> 16) & 0xFF); 107 | ptr[3] = (u8) ((val >> 24) & 0xFF); 108 | } 109 | 110 | inline void sh_le(u16 *data, u16 val) 111 | { 112 | u8 *ptr = (u8*) data; 113 | 114 | ptr[0] = (u8) (val & 0xFF); 115 | ptr[1] = (u8) ((val >> 8) & 0xFF); 116 | } 117 | 118 | #define SW_LE(x, v) (sw_le((u32*) &(x), (v))) 119 | #define SW_BE(x, v) ((x) = (v)) 120 | #define SH_LE(x, v) (sh_le((u16*) &(x), (v))) 121 | #define SH_BE(x, v) ((x) = (v)) 122 | 123 | #else 124 | 125 | inline void sw_be(u32 *data, u32 val) 126 | { 127 | u8 *ptr = (u8*) data; 128 | 129 | ptr[0] = (u8) ((val >> 24) & 0xFF); 130 | ptr[1] = (u8) ((val >> 16) & 0xFF); 131 | ptr[2] = (u8) ((val >> 8) & 0xFF); 132 | ptr[3] = (u8) (val & 0xFF); 133 | } 134 | 135 | inline void sh_be(u16 *data, u16 val) 136 | { 137 | u8* ptr = (u8*) data; 138 | 139 | ptr[0] = (u8) ((val >> 8) & 0xFF); 140 | ptr[1] = (u8) (val & 0xFF); 141 | } 142 | 143 | #define SW_LE(x, v) ((x) = (v)) 144 | #define SW_BE(x, v) (sw_be((u32*) &(x), (v))) 145 | #define SH_LE(x, v) ((x) = (v)) 146 | #define SH_BE(x, v) (sh_be((u16*) &(x), (v))) 147 | 148 | #endif 149 | 150 | #define SW(x, v) (SW_LE(x, v)) 151 | #define SH(x, v) (SH_LE(x, v)) 152 | 153 | 154 | /* Do a safe alloc which should work on vc6 or latest gcc etc */ 155 | /* If alloc fails will always return NULL */ 156 | #define SAFE_ALLOC(p, t) try { (p) = new t; } catch(...) { (p) = NULL; } 157 | 158 | #ifndef MAXPATH 159 | #define MAXPATH 256 160 | #endif 161 | 162 | #endif 163 | --------------------------------------------------------------------------------