Skip to content

Commit

Permalink
Merge pull request #167 from chaoticgd/sndll_fix
Browse files Browse the repository at this point in the history
Fix issue where absolute SNDLL symbols were being treated as relative
  • Loading branch information
chaoticgd authored Jan 28, 2024
2 parents 7f65c1b + ea55b28 commit 84da97f
Show file tree
Hide file tree
Showing 4 changed files with 14 additions and 10 deletions.
17 changes: 10 additions & 7 deletions src/ccc/sndll.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ CCC_PACKED_STRUCT(SNDLLSymbolHeader,
)

static Result<SNDLLFile> parse_sndll_common(
std::span<const u8> image, Address address, const SNDLLHeaderCommon& common, SNDLLVersion version);
std::span<const u8> image, Address address, bool symbols_relative, const SNDLLHeaderCommon& common, SNDLLVersion version);
static const char* sndll_symbol_type_to_string(SNDLLSymbolType type);

Result<SNDLLFile> parse_sndll_file(std::span<const u8> image, Address address)
Result<SNDLLFile> parse_sndll_file(std::span<const u8> image, Address address, bool symbols_relative)
{
const u32* magic = get_packed<u32>(image, 0);
CCC_CHECK((*magic & 0xffffff) == CCC_FOURCC("SNR\00"), "Not a SNDLL %s.", address.valid() ? "section" : "file");
Expand All @@ -60,24 +60,25 @@ Result<SNDLLFile> parse_sndll_file(std::span<const u8> image, Address address)
case '1': {
const SNDLLHeaderV1* header = get_packed<SNDLLHeaderV1>(image, 0);
CCC_CHECK(header, "File too small to contain SNDLL V1 header.");
return parse_sndll_common(image, address, header->common, SNDLL_V1);
return parse_sndll_common(image, address, symbols_relative, header->common, SNDLL_V1);
}
case '2': {
const SNDLLHeaderV2* header = get_packed<SNDLLHeaderV2>(image, 0);
CCC_CHECK(header, "File too small to contain SNDLL V2 header.");
return parse_sndll_common(image, address, header->common, SNDLL_V2);
return parse_sndll_common(image, address, symbols_relative, header->common, SNDLL_V2);
}
}

return CCC_FAILURE("Unknown SNDLL version '%c'.", version);
}

static Result<SNDLLFile> parse_sndll_common(
std::span<const u8> image, Address address, const SNDLLHeaderCommon& common, SNDLLVersion version)
std::span<const u8> image, Address address, bool symbols_relative, const SNDLLHeaderCommon& common, SNDLLVersion version)
{
SNDLLFile sndll;

sndll.address = address;
sndll.symbols_relative = symbols_relative;
sndll.version = version;

if(common.elf_path) {
Expand Down Expand Up @@ -122,15 +123,17 @@ Result<void> import_sndll_symbols(
switch(symbol.type) {
case SNDLLSymbolType::RELATIVE:
case SNDLLSymbolType::WEAK: {
u32 base_address = sndll.symbols_relative ? sndll.address.get_or_zero() : 0;

Result<Label*> label = database.labels.create_symbol(
symbol.string, source, module_symbol, sndll.address.get_or_zero() + symbol.value, importer_flags, demangler);
symbol.string, source, module_symbol, base_address + symbol.value, importer_flags, demangler);
CCC_RETURN_IF_ERROR(label);

break;
}
case SNDLLSymbolType::ABSOLUTE: {
Result<Label*> label = database.labels.create_symbol(
symbol.string, source, module_symbol,symbol.value, importer_flags, demangler);
symbol.string, source, module_symbol, symbol.value, importer_flags, demangler);
CCC_RETURN_IF_ERROR(label);

break;
Expand Down
3 changes: 2 additions & 1 deletion src/ccc/sndll.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,15 @@ struct SNDLLSymbol {

struct SNDLLFile {
Address address;
bool symbols_relative;
SNDLLVersion version;
std::string elf_path;
std::vector<SNDLLSymbol> symbols;
};

// If a valid address is passed, the pointers in the header will be treated as
// addresses, otherwise they will be treated as file offsets.
Result<SNDLLFile> parse_sndll_file(std::span<const u8> image, Address address = Address());
Result<SNDLLFile> parse_sndll_file(std::span<const u8> image, Address address, bool symbols_relative);

Result<void> import_sndll_symbols(
SymbolDatabase& database,
Expand Down
2 changes: 1 addition & 1 deletion src/ccc/symbol_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Result<std::unique_ptr<SymbolFile>> parse_symbol_file(std::vector<u8> image, std
}
case CCC_FOURCC("SNR1"):
case CCC_FOURCC("SNR2"): {
Result<SNDLLFile> sndll = parse_sndll_file(image);
Result<SNDLLFile> sndll = parse_sndll_file(image, Address(), true);
CCC_RETURN_IF_ERROR(sndll);

symbol_file = std::make_unique<SNDLLSymbolFile>(std::move(*sndll));
Expand Down
2 changes: 1 addition & 1 deletion src/ccc/symbol_table.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ Result<std::unique_ptr<SymbolTable>> create_elf_symbol_table(
std::span<const u8> data = std::span(elf.image).subspan(section.offset, section.size);

if(data.size() >= 4 && data[0] != '\0') {
Result<SNDLLFile> file = parse_sndll_file(data, section.address);
Result<SNDLLFile> file = parse_sndll_file(data, section.address, false);
CCC_RETURN_IF_ERROR(file);

symbol_table = std::make_unique<SNDLLSymbolTable>(std::make_shared<SNDLLFile>(std::move(*file)));
Expand Down

0 comments on commit 84da97f

Please sign in to comment.