bool ElfDecoder::decode(address addr, char *buf, int buflen, int* offset, const char* filepath) {
  assert(filepath, "null file path");
  assert(buf != NULL && buflen > 0, "Invalid buffer");
  if (has_error()) return false;
  ElfFile* file = get_elf_file(filepath);
  if (file == NULL) {
    return false;
  }

  if (!file->decode(addr, buf, buflen, offset)) {
    return false;
  }
  if (buf[0] != '\0') {
    demangle(buf, buf, buflen);
  }
  return true;
}
ElfFile* ElfDecoder::get_elf_file(const char* filepath) {
  ElfFile* file;

  file = _opened_elf_files;
  while (file != NULL) {
    if (file->same_elf_file(filepath)) {
      return file;
    }
    file = file->next();
  }

  file = new (std::nothrow)ElfFile(filepath);
  if (file != NULL) {
    if (_opened_elf_files != NULL) {
      file->set_next(_opened_elf_files);
    }
    _opened_elf_files = file;
  }

  return file;
}
Exemplo n.º 3
0
ElfFile* Decoder::get_elf_file(const char* filepath) {
  if (_decoder_status != no_error) {
    return NULL;
  }
  ElfFile* file = _opened_elf_files;
  while (file != NULL) {
    if (file->same_elf_file(filepath)) {
      return file;
    }
    file = file->m_next;
  }

  file = new ElfFile(filepath);
  if (file == NULL) {
    _decoder_status = out_of_memory;
  }
  if (_opened_elf_files != NULL) {
    file->m_next = _opened_elf_files;
  }

  _opened_elf_files = file;
  return file;
}
Exemplo n.º 4
0
Decoder::decoder_status Decoder::decode(address addr, const char* filepath, char *buf, int buflen, int *offset) {
  if (_decoder_status != no_error) {
    return _decoder_status;
  }

  ElfFile* file = get_elf_file(filepath);
  if (_decoder_status != no_error) {
    return _decoder_status;
  }

  const char* symbol = file->decode(addr, offset);
  if (file->get_status() == out_of_memory) {
    _decoder_status = out_of_memory;
    return _decoder_status;
  } else if (symbol != NULL) {
    if (!demangle(symbol, buf, buflen)) {
      jio_snprintf(buf, buflen, "%s", symbol);
    }
    return no_error;
  } else {
    return symbol_not_found;
  }
}
Exemplo n.º 5
0
void Symbolizer::symbolize(const uintptr_t* addresses,
                           SymbolizedFrame* frames,
                           size_t addressCount) {
  size_t remaining = 0;
  for (size_t i = 0; i < addressCount; ++i) {
    auto& frame = frames[i];
    if (!frame.found) {
      ++remaining;
      frame.name.clear();
      frame.location = Dwarf::LocationInfo();
    }
  }

  if (remaining == 0) {  // we're done
    return;
  }

  int fd = openNoInt("/proc/self/maps", O_RDONLY);
  if (fd == -1) {
    return;
  }

  char buf[PATH_MAX + 100];  // Long enough for any line
  LineReader reader(fd, buf, sizeof(buf));

  char fileNameBuf[PATH_MAX];

  while (remaining != 0) {
    StringPiece line;
    if (reader.readLine(line) != LineReader::kReading) {
      break;
    }

    // Parse line
    uintptr_t from;
    uintptr_t to;
    StringPiece fileName;
    if (!parseProcMapsLine(line, from, to, fileName)) {
      continue;
    }

    bool first = true;
    ElfFile* elfFile = nullptr;

    // See if any addresses are here
    for (size_t i = 0; i < addressCount; ++i) {
      auto& frame = frames[i];
      if (frame.found) {
        continue;
      }

      uintptr_t address = addresses[i];

      if (from > address || address >= to) {
        continue;
      }

      // Found
      frame.found = true;
      --remaining;

      // Open the file on first use
      if (first) {
        first = false;
        if (fileCount_ < kMaxFiles &&
            !fileName.empty() &&
            fileName.size() < sizeof(fileNameBuf)) {
          memcpy(fileNameBuf, fileName.data(), fileName.size());
          fileNameBuf[fileName.size()] = '\0';
          auto& f = files_[fileCount_++];
          if (f.openNoThrow(fileNameBuf) != -1) {
            elfFile = &f;
          }
        }
      }

      if (!elfFile) {
        continue;
      }

      // Undo relocation
      uintptr_t fileAddress = address - from + elfFile->getBaseAddress();
      auto sym = elfFile->getDefinitionByAddress(fileAddress);
      if (!sym.first) {
        continue;
      }
      auto name = elfFile->getSymbolName(sym);
      if (name) {
        frame.name = name;
      }

      Dwarf(elfFile).findAddress(fileAddress, frame.location);
    }
  }

  closeNoInt(fd);
}
Exemplo n.º 6
0
bool ElfRelocator::init(const std::wstring& inputName)
{
	relocator = Arch->getElfRelocator();
	if (relocator == NULL)
	{
		Logger::printError(Logger::Error,L"Object importing not supported for this architecture");
		return false;
	}

	auto inputFiles = loadArArchive(inputName);
	if (inputFiles.size() == 0)
	{
		Logger::printError(Logger::Error,L"Could not load library");
		return false;
	}

	for (ArFileEntry& entry: inputFiles)
	{
		ElfRelocatorFile file;

		ElfFile* elf = new ElfFile();
		if (elf->load(entry.data,false) == false)
		{
			Logger::printError(Logger::Error,L"Could not load object file %s",entry.name);
			return false;
		}

		if (elf->getType() != 1)
		{
			Logger::printError(Logger::Error,L"Unexpected ELF type %d in object file %s",elf->getType(),entry.name);
			return false;
		}

		if (elf->getSegmentCount() != 0)
		{
			Logger::printError(Logger::Error,L"Unexpected segment count %d in object file %s",elf->getSegmentCount(),entry.name);
			return false;
		}

		// load all relevant sections of this file
		for (size_t s = 0; s < elf->getSegmentlessSectionCount(); s++)
		{
			ElfSection* sec = elf->getSegmentlessSection(s);
			if (!(sec->getFlags() & SHF_ALLOC))
				continue;

			if (sec->getType() == SHT_PROGBITS || sec->getType() == SHT_NOBITS || sec->getType() == SHT_INIT_ARRAY)
			{
				ElfRelocatorSection sectionEntry;
				sectionEntry.section = sec;
				sectionEntry.index = s;
				sectionEntry.relSection = NULL;
				sectionEntry.label = NULL;

				// search relocation section
				for (size_t k = 0; k < elf->getSegmentlessSectionCount(); k++)
				{
					ElfSection* relSection = elf->getSegmentlessSection(k);
					if (relSection->getType() != SHT_REL)
						continue;
					if (relSection->getInfo() != s)
						continue;

					// got it
					sectionEntry.relSection = relSection;
					break;
				}

				// keep track of constructor sections
				if (sec->getName() == ".ctors" || sec->getName() == ".init_array")
				{
					ElfRelocatorCtor ctor;
					ctor.symbolName = Global.symbolTable.getUniqueLabelName();
					ctor.size = sec->getSize();

					sectionEntry.label = Global.symbolTable.getLabel(ctor.symbolName,-1,-1);
					sectionEntry.label->setDefined(true);

					ctors.push_back(ctor);
				}

				file.sections.push_back(sectionEntry);
			}
		}

		// init exportable symbols
		for (int i = 0; i < elf->getSymbolCount(); i++)
		{
			Elf32_Sym symbol;
			bool found = elf->getSymbol(symbol, i);

			if (ELF32_ST_BIND(symbol.st_info) == STB_GLOBAL && symbol.st_shndx != 0)
			{
				ElfRelocatorSymbol symEntry;
				symEntry.type = ELF32_ST_TYPE(symbol.st_info);
				symEntry.name = convertUtf8ToWString(elf->getStrTableString(symbol.st_name));
				symEntry.relativeAddress = symbol.st_value;
				symEntry.section = symbol.st_shndx;
				symEntry.size = symbol.st_size;
				symEntry.label = NULL;

				file.symbols.push_back(symEntry);
			}
		}

		file.elf = elf;
		file.name = entry.name;
		files.push_back(file);
	}

	return true;
}
Exemplo n.º 7
0
bool ElfRelocator::relocateFile(ElfRelocatorFile& file, u64& relocationAddress)
{
	ElfFile* elf = file.elf;
	u64 start = relocationAddress;

	// calculate address for each section
	std::map<u64,u64> relocationOffsets;
	for (ElfRelocatorSection& entry: file.sections)
	{
		ElfSection* section = entry.section;
		size_t index = entry.index;
		int size = section->getSize();

		while (relocationAddress % section->getAlignment())
			relocationAddress++;

		if (entry.label != NULL)
			entry.label->setValue(relocationAddress);

		relocationOffsets[index] = relocationAddress;
		relocationAddress += size;
	}

	size_t dataStart = outputData.size();
	outputData.reserveBytes((size_t)(relocationAddress-start));

	// load sections
	bool error = false;
	for (ElfRelocatorSection& entry: file.sections)
	{
		ElfSection* section = entry.section;
		size_t index = entry.index;

		if (section->getType() == SHT_NOBITS)
		{
			// reserveBytes initialized the data to 0 already
			continue;
		}
		
		ByteArray sectionData = section->getData();

		// relocate if necessary
		ElfSection* relSection = entry.relSection;
		if (relSection != NULL)
		{
			for (unsigned int relOffset = 0; relOffset < relSection->getSize(); relOffset += sizeof(Elf32_Rel))
			{
				Elf32_Rel rel;
				loadRelocation(rel, relSection->getData(), relOffset, elf->isBigEndian());
				int pos = rel.r_offset;

				int symNum = rel.getSymbolNum();
				if (symNum <= 0)
				{
					Logger::queueError(Logger::Warning,L"Invalid symbol num %06X",symNum);
					error = true;
					continue;
				}

				Elf32_Sym sym;
				auto found = elf->getSymbol(sym, symNum);
				int symSection = sym.st_shndx;
				
				RelocationData relData;
				relData.opcode = sectionData.getDoubleWord(pos, elf->isBigEndian());
				relData.opcodeOffset = pos+relocationOffsets[index];
				relocator->setSymbolAddress(relData,sym.st_value,sym.st_info & 0xF);

				// externs?
				if (relData.targetSymbolType == STT_NOTYPE && sym.st_shndx == 0)
				{
					std::wstring symName = toWLowercase(elf->getStrTableString(sym.st_name));

					Label* label = Global.symbolTable.getLabel(symName,-1,-1);
					if (label == NULL)
					{
						Logger::queueError(Logger::Error,L"Invalid external symbol %s",symName);	
						error = true;
						continue;
					}
					if (label->isDefined() == false)
					{
						Logger::queueError(Logger::Error,L"Undefined external symbol %s in file %s",symName,file.name);
						error = true;
						continue;
					}
					
					relData.relocationBase = (unsigned int) label->getValue();
					relData.targetSymbolType = label->isData() ? STT_OBJECT : STT_FUNC;
					relData.targetSymbolInfo = label->getInfo();
				} else {
					relData.relocationBase = relocationOffsets[symSection]+relData.symbolAddress;
				}

				if (relocator->relocateOpcode(rel.getType(),relData) == false)
				{
					Logger::queueError(Logger::Error,relData.errorMessage);
					error = true;
					continue;
				}

				sectionData.replaceDoubleWord(pos,relData.opcode, elf->isBigEndian());
			}
		}

		size_t arrayStart = (size_t) (dataStart+relocationOffsets[index]-start);
		memcpy(outputData.data(arrayStart),sectionData.data(),sectionData.size());
	}
	
	// now update symbols
	for (ElfRelocatorSymbol& sym: file.symbols)
	{
		u64 oldAddress = sym.relocatedAddress;

		switch (sym.section)
		{
		case SHN_ABS:		// address does not change
			sym.relocatedAddress = sym.relativeAddress;
			break;
		case SHN_COMMON:	// needs to be allocated. relativeAddress gives alignment constraint
			{
				u64 start = relocationAddress;

				while (relocationAddress % sym.relativeAddress)
					relocationAddress++;

				sym.relocatedAddress = relocationAddress;
				relocationAddress += sym.size;
				outputData.reserveBytes((size_t)(relocationAddress-start));
			}
			break;
		default:			// normal relocated symbol
			sym.relocatedAddress = sym.relativeAddress+relocationOffsets[sym.section];
			break;
		}

		if (sym.label != NULL)
			sym.label->setValue(sym.relocatedAddress);

		if (oldAddress != sym.relocatedAddress)
			dataChanged = true;
	}

	return !error;
}
Exemplo n.º 8
0
// convert an elf file to a dol file
// 
// args:        dol file object
//                        elf filename
// returns:        true if successful
bool convertElfFileToDol(DolFile& dolFile, const char *elfFilename)
{
        // open elf input file
        ElfFile elfFile;
        if(!elfFile.open(elfFilename))
                return false;
        
        if(!elfFile.isPpc())
                printf("Elf file doesnt seem to be for PPC!\n");
        
        // create a temp file to store section data during copy
        FILE* temp_fd = fopen("~temp.tmp", "w+b");
        if(temp_fd == 0)
        {
                elfFile.close();
                return false;
        }
        
        // check which sections to add to dol file
        for(u32 i=0; i<elfFile.getNumSections(); i++)
        {
                // check if section type is 'PROGBITS'
                // these are the sections required for the dol file
                if(elfFile.getSectionType(i) == SHT_PROGBITS)
                {
                        // get section data from elf file
                        fseek(temp_fd, 0, SEEK_SET);
                        elfFile.extractSectionData(i, temp_fd);
                        fseek(temp_fd, 0, SEEK_SET);
                        
                        // sections with 'EXEC' flags are program code, and so
                        // should be added as a TEXT section in the dol file
                        if(elfFile.getSectionFlags(i) & SHF_EXECINSTR)
                        {
                                // add section data to dol file
                                dolFile.addTextSection(temp_fd, elfFile.getSectionAddress(i), elfFile.getSectionSize(i));
                        }
                        else
                        {
                                // add section data to dol file
                                if (elfFile.getSectionAddress(i) != 0 && elfFile.getSectionSize(i) != 0)
                                      dolFile.addDataSection(temp_fd, elfFile.getSectionAddress(i), elfFile.getSectionSize(i));
                        }
                }
                else
                {
                        // check for bss section by checking section name for '.bss'
                        char *name = 0;
                        if(elfFile.getSectionName(i, name) != ERROR_RETURN)
                        {
                                if(strcasecmp(name, ".bss") == 0)
                                {
                                        dolFile.setBssAddress(elfFile.getSectionAddress(i));
                                        dolFile.setBssSize(elfFile.getSectionSize(i));
                                }
                                delete[] name;
                        }
                }
        }
        
        // set dol files entry point
        dolFile.setEntryPoint(elfFile.getEntryPoint());
        
        // finish up
        fclose(temp_fd);
        remove("~temp.tmp");
        elfFile.close();
        printf(        "\nConverted %s to %s\n", elfFilename, dolFile.getFilename());
        return true;
}
Exemplo n.º 9
0
// dump dol file to an elf file
// 
// args:        dol file object
// returns:        true if successful
bool dumpDolToElfFile(const DolFile& dolFile)
{
        // work out filename to use for elf file
        char elfFilename[256];
        strcpy(elfFilename, dolFile.getFilename());
        ChangeFileExtension(elfFilename, "elf");
        
        // create elf output file
        ElfFile elfFile;
        if(!elfFile.create(elfFilename, ELFDATA2MSB))
                return false;
        
        // set elf file as PPC
        elfFile.setMachineType(EM_PPC);
        
        // set entry point in elf file
        elfFile.setEntryPoint(dolFile.getEntryPoint());
        
        // create a temp file to store section data during copy
        FILE* temp_fd = fopen("~temp.tmp", "w+b");
        if(temp_fd == 0)
        {
                elfFile.close();
                return false;
        }
        char name[32];
        
        // add dol text sections to elf file
        for(u32 i=0; i<dolFile.getNumTextSections(); i++)
        {
                // get section data from dol file
                fseek(temp_fd, 0, SEEK_SET);
                dolFile.extractTextSection(i, temp_fd);
                sprintf(name, ".text%d", i);
                // add section data to elf file
                fseek(temp_fd, 0, SEEK_SET);
                elfFile.addSection(temp_fd, dolFile.getTextAddress(i), dolFile.getTextSize(i),
                        name, SHT_PROGBITS, SHF_ALLOC|SHF_EXECINSTR, 32);
                
                // add a program header for the section just added
                // the section just added, was added as the last section
//                u32 offset = elfFile.getSectionOffset(elfFile.getNumSections() - 1);
//                elfFile.addProgramHeader(dolFile.getTextAddress(i), dolFile.getTextSize(i), offset, PT_LOAD, PF_EXEC|PF_READ, 32);
        }
        // add dol data sections to elf file
        for(u32    i=0; i<dolFile.getNumDataSections(); i++)
        {
                // get section data from dol file
                fseek(temp_fd, 0, SEEK_SET);
                dolFile.extractDataSection(i, temp_fd);
                sprintf(name, ".data%d", i);
                // add section data to elf file
                fseek(temp_fd, 0, SEEK_SET);
                elfFile.addSection(temp_fd, dolFile.getDataAddress(i), dolFile.getDataSize(i),
                        name, SHT_PROGBITS, SHF_ALLOC|SHF_WRITE, 32);
                
                // add a program header for the section just added
                // the section just added, was added as the last section
//                u32 offset = elfFile.getSectionOffset(elfFile.getNumSections() - 1);
//                elfFile.addProgramHeader(dolFile.getDataAddress(i), dolFile.getDataSize(i), offset, PT_LOAD, PF_WRITE|PF_READ, 32);
        }
        
        // add bss section to elf file
        elfFile.addSectionHeader(dolFile.getBssAddress(), dolFile.getBssSize(),
                ".bss", 0, SHT_NOBITS, SHF_WRITE|SHF_ALLOC, 1);
        // add a program header for the section just added
        // the section just added, was added as the last section
//        u32 index = elfFile.getNumSections() - 1;
//        elfFile.addProgramHeader(elfFile.getSectionAddress(index), elfFile.getSectionSize(index), elfFile.getSectionOffset(index), PT_LOAD, PF_WRITE|PF_READ, 32);
        
        // finish up
        fclose(temp_fd);
        remove("~temp.tmp");
        elfFile.close();
        printf(        "\nConverted %s to to %s\n", dolFile.getFilename(), elfFilename);
        return true;
}