diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java index d5bc9add71..ffa05acc67 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java @@ -649,8 +649,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { long entry = elf.e_entry(); // already adjusted for pre-link if (entry != 0 && (elf.isExecutable() || elf.isSharedObject())) { - Address entryAddr = - createEntryFunction(ElfLoader.ELF_ENTRY_FUNCTION_NAME, entry); + Address entryAddr = createEntryFunction(ElfLoader.ELF_ENTRY_FUNCTION_NAME, entry); if (entryAddr != null) { addElfHeaderReferenceMarkup(elf.getEntryComponentOrdinal(), entryAddr); Function entryFunc = program.getFunctionManager().getFunctionAt(entryAddr); @@ -765,7 +764,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { createEntryFunction(name, entryAddress); return entryAddress; } - + /** * Attempt to create an entry point function. * Note: entries in the dynamic table appear to have any pre-link adjustment already applied. @@ -778,7 +777,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { MemoryBlock block = memory.getBlock(entryAddress); if (block == null || !block.isExecute()) { - return; + return; } entryAddress = elf.getLoadAdapter().creatingFunction(this, entryAddress); @@ -996,6 +995,9 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { int symbolIndex = reloc.getSymbolIndex(); String symbolName = symbolTable != null ? symbolTable.getSymbolName(symbolIndex) : ""; + if (symbolName != null && isUnsupportedASCIISymbolName(symbolName)) { + symbolName = getEscapedSymbolName(symbolName); + } Address baseAddress = relocationSpace.getTruncatedAddress(baseWordOffset, true); @@ -1116,9 +1118,8 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { hasConflict = nextRelocAddr != null && nextRelocAddr.compareTo(maxAddr) <= 0; } if (hasConflict) { - Msg.warn(this, - "Artificial relocation for " + address + - " conflicts with a previous relocation"); + Msg.warn(this, "Artificial relocation for " + address + + " conflicts with a previous relocation"); } relocationTable.add(address, Status.APPLIED_OTHER, 0, null, length, null); return true; @@ -2093,6 +2094,12 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { isPrimary = (existingSym == null); } + if (name != null && isUnsupportedASCIISymbolName(name)) { + String escapedName = getEscapedSymbolName(name); + log("Unsupported ASCII symbol name has been escaped: \"" + escapedName + "\""); + name = escapedName; + } + createSymbol(address, name, isPrimary, elfSymbol.isAbsolute(), null); // NOTE: treat weak symbols as global so that other programs may link to them. @@ -2127,6 +2134,39 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { } } + private boolean isUnsupportedASCIISymbolName(String name) { + for (char c : name.toCharArray()) { + if (!StringUtilities.isAsciiChar(c) || c == ' ') { + return true; + } + } + return false; + } + + private String getEscapedSymbolName(String name) { + StringBuilder escapedBuf = new StringBuilder(); + for (char c : name.toCharArray()) { + if (c < 0 || c > 0x7f) { + // format non-ASCII as escaped numeric hex value \xNN + escapedBuf.append("\\x%02x".formatted((int) c)); + } + else if (c < ' ') { + // format as ^Control character for consistency with readelf + c += 64; // get ASCII control character, starts with ^@ + escapedBuf.append('^'); + escapedBuf.append(c); + } + else if (c == 0x7f) { + // format as ^? character for consistency with readelf + escapedBuf.append("^?"); + } + else { + escapedBuf.append(c); + } + } + return escapedBuf.toString(); + } + @Override public void setElfSymbolAddress(ElfSymbol elfSymbol, Address address) { symbolMap.put(elfSymbol, address); @@ -3627,14 +3667,13 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { // Msg.debug(this, // "Loading block " + name + " at " + start + " from file offset " + fileOffset); - long compSectOrigSize = loadable instanceof ElfSectionHeader header && header.isCompressed() - ? header.getSize() - : -1; + long compSectOrigSize = + loadable instanceof ElfSectionHeader header && header.isCompressed() ? header.getSize() + : -1; String blockComment = comment; if (compSectOrigSize >= 0) { - blockComment += - " (decompressed, original length: 0x%x)".formatted(compSectOrigSize); + blockComment += " (decompressed, original length: 0x%x)".formatted(compSectOrigSize); } else if ((fileOffset + revisedLength - 1) >= fileBytes.getSize()) { // ensure valid length for non-compressed items @@ -3650,15 +3689,13 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { try { if (loadable != null && loadable.hasFilteredLoadInputStream(this, start)) { // block is unable to map directly to file bytes - load from input stream - try (InputStream is = - loadable.getFilteredLoadInputStream(this, start, revisedLength, - (errorMsg, th) -> { - String loadableTypeStr = - compSectOrigSize >= 0 ? "compressed section " : ""; - log.appendMsg("Error when reading %s[%s]: %s".formatted(loadableTypeStr, - name, errorMsg)); - Msg.error(this, errorMsg, th); - })) { + try (InputStream is = loadable.getFilteredLoadInputStream(this, start, + revisedLength, (errorMsg, th) -> { + String loadableTypeStr = compSectOrigSize >= 0 ? "compressed section " : ""; + log.appendMsg("Error when reading %s[%s]: %s".formatted(loadableTypeStr, + name, errorMsg)); + Msg.error(this, errorMsg, th); + })) { block = MemoryBlockUtils.createInitializedBlock(program, isOverlay, name, start, is, revisedLength, blockComment, BLOCK_SOURCE_NAME, r, w, x, log, monitor); } @@ -3673,8 +3710,8 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper { finally { if (block == null) { Address end = start.addNoWrap(revisedLength - 1); - log("Unexpected ELF memory block load conflict when creating '" + name + - "' at " + start.toString(true) + "-" + end.toString(true)); + log("Unexpected ELF memory block load conflict when creating '" + name + "' at " + + start.toString(true) + "-" + end.toString(true)); } } return block;