├── belf ├── dllmain.cpp ├── utils.h ├── dynlib.h ├── dynlib.cpp ├── belf.vcxproj.filters ├── elfr_sce.h ├── utils.cpp ├── belf.vcxproj ├── belf_loader.cpp └── reader.cpp ├── README.md ├── belf.sln ├── .gitignore └── LICENSE /belf/dllmain.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balika011/belf/HEAD/belf/dllmain.cpp -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # belf 2 | Balika011's PlayStation 4 ELF loader for IDA Pro 7.0/7.1 3 | 4 | Special thanks to [@aerosoul94](https://github.com/aerosoul94) for [dynlib](https://github.com/aerosoul94/dynlib) 5 | 6 | His plugin provided a good reference. 7 | -------------------------------------------------------------------------------- /belf/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef __UTILS_H__ 2 | #define __UTILS_H__ 3 | 4 | #include 5 | 6 | qstring ph_type_to_string(uint32 p_type); 7 | qstring dyntag_to_string(uint64 tag); 8 | int decode_base64(const char *str, int *a2); 9 | 10 | #endif -------------------------------------------------------------------------------- /belf/dynlib.h: -------------------------------------------------------------------------------- 1 | #ifndef __DYNLIB_H__ 2 | #define __DYNLIB_H__ 3 | 4 | #include 5 | #include 6 | 7 | class DynLib 8 | { 9 | public: 10 | DynLib(const char *xml); 11 | ~DynLib(); 12 | void LoadXML(const char *); 13 | void setSelfModuleStrIndex(uint32 idx) { m_selfModuleStrIndex = idx; } 14 | void addModule(uint32 id, uint32 nameidx) { m_module_map[id] = nameidx; } 15 | 16 | bool isObfuscated(const char *sym); 17 | uint32 lookup(const char *obf); 18 | qstring deobfuscate(qstring lib, qstring obf); 19 | 20 | private: 21 | struct dynlib_entry 22 | { 23 | qstring obf; 24 | qstring lib; 25 | qstring sym; 26 | }; 27 | std::vector m_entries; 28 | 29 | uint32 m_selfModuleStrIndex = 0; 30 | std::unordered_map m_module_map; 31 | }; 32 | 33 | #endif -------------------------------------------------------------------------------- /belf.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27703.2000 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "belf", "belf\belf.vcxproj", "{2D75A06D-1D61-4A5A-BC67-77C838919697}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {2D75A06D-1D61-4A5A-BC67-77C838919697}.Debug|x64.ActiveCfg = Debug|x64 17 | {2D75A06D-1D61-4A5A-BC67-77C838919697}.Debug|x64.Build.0 = Debug|x64 18 | {2D75A06D-1D61-4A5A-BC67-77C838919697}.Debug|x86.ActiveCfg = Debug|Win32 19 | {2D75A06D-1D61-4A5A-BC67-77C838919697}.Debug|x86.Build.0 = Debug|Win32 20 | {2D75A06D-1D61-4A5A-BC67-77C838919697}.Release|x64.ActiveCfg = Release|x64 21 | {2D75A06D-1D61-4A5A-BC67-77C838919697}.Release|x64.Build.0 = Release|x64 22 | {2D75A06D-1D61-4A5A-BC67-77C838919697}.Release|x86.ActiveCfg = Release|Win32 23 | {2D75A06D-1D61-4A5A-BC67-77C838919697}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {6BE39ED1-F095-42E5-B8B3-B441C8AB3E44} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /belf/dynlib.cpp: -------------------------------------------------------------------------------- 1 | #include "dynlib.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "TinyXML/tinyxml.h" 8 | #include "utils.h" 9 | 10 | DynLib::DynLib(const char *xml) 11 | { 12 | LoadXML(xml); 13 | } 14 | 15 | DynLib::~DynLib() 16 | { 17 | 18 | } 19 | 20 | void DynLib::LoadXML(const char *db) 21 | { 22 | TiXmlDocument xml; 23 | if (!xml.LoadFile(db)) 24 | loader_failure("Failed to load database file (%s).", db); 25 | 26 | TiXmlElement *DynlibDatabase = xml.FirstChildElement(); 27 | if (!DynlibDatabase || strcmp(DynlibDatabase->Value(), "DynlibDatabase")) 28 | loader_failure("Database requires \"DynlibDatabase\" header."); 29 | 30 | TiXmlElement *e = DynlibDatabase->FirstChildElement(); 31 | if (!e) 32 | loader_failure("Database has no entries in \"DynlibDatabase\"."); 33 | 34 | do { 35 | const char *obf = e->Attribute("obf"); 36 | if (!obf) 37 | loader_failure("Entry needs to have an \"obf\" attribute."); 38 | const char *lib = e->Attribute("lib"); 39 | if (!lib) 40 | loader_failure("Entry needs to have an \"lib\" attribute."); 41 | const char *sym = e->Attribute("sym"); 42 | if (!sym) 43 | loader_failure("Entry needs to have an \"sym\" attribute."); 44 | 45 | dynlib_entry entry; 46 | entry.obf.sprnt(obf); 47 | entry.lib.sprnt(lib); 48 | entry.sym.sprnt(sym); 49 | m_entries.push_back(entry); 50 | } while (e = e->NextSiblingElement()); 51 | } 52 | 53 | bool DynLib::isObfuscated(const char *sym) 54 | { 55 | const char *p; 56 | if (strlen(sym) >= 13) 57 | if ((p = strchr(sym, '#')) != NULL) // contains first # 58 | if ((p - sym) == 11) // obfuscated symbol is 11 chars 59 | if ((p = strchr(p + 1, '#')) != NULL) // contains second # 60 | return true; 61 | 62 | return false; 63 | } 64 | 65 | uint32 DynLib::lookup(const char *obf) 66 | { 67 | int modid; 68 | 69 | const char *lib = strchr(obf, '#'); 70 | if (lib == NULL) { 71 | msg("No lib id in this symbol.\n"); 72 | return -1; 73 | } 74 | 75 | lib = strchr(lib + 1, '#'); 76 | if (lib == NULL) { 77 | msg("No mod id in this symbol.\n"); 78 | return -1; 79 | } 80 | 81 | if (decode_base64(lib + 1, &modid)) { 82 | msg("Invalid module id!\n"); 83 | return -1; 84 | } 85 | 86 | if (modid == 0) 87 | return m_selfModuleStrIndex; 88 | 89 | if (m_module_map.find(modid) != m_module_map.end()) 90 | { 91 | return m_module_map.at(modid); 92 | } 93 | 94 | return -1; 95 | } 96 | 97 | qstring DynLib::deobfuscate(qstring lib, qstring obf) 98 | { 99 | for (const dynlib_entry& entry : m_entries) 100 | { 101 | if (entry.lib == lib && obf.substr(0, 11) == entry.obf) 102 | return entry.sym; 103 | } 104 | 105 | return ""; 106 | } -------------------------------------------------------------------------------- /belf/belf.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {63b0314f-aa62-47df-b4a2-4d18fd44e630} 18 | 19 | 20 | {a6610ad9-9a69-480c-8738-dc150e76aba8} 21 | 22 | 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files\TinyXML 35 | 36 | 37 | Source Files\TinyXML 38 | 39 | 40 | Source Files\TinyXML 41 | 42 | 43 | Source Files\TinyXML 44 | 45 | 46 | Source Files 47 | 48 | 49 | Source Files 50 | 51 | 52 | 53 | 54 | Header Files 55 | 56 | 57 | Header Files\TinyXML 58 | 59 | 60 | Header Files\TinyXML 61 | 62 | 63 | Header Files 64 | 65 | 66 | Header Files 67 | 68 | 69 | -------------------------------------------------------------------------------- /belf/elfr_sce.h: -------------------------------------------------------------------------------- 1 | #ifndef __ELFR_SCE_H__ 2 | #define __ELFR_SCE_H__ 3 | 4 | #include 5 | #include 6 | 7 | #ifndef __ELFBASE_H__ 8 | #include 9 | #endif 10 | 11 | enum elf_ET_SCE 12 | { 13 | ET_SCE_EXEC = 0xfe00, // PS4 Executable 14 | ET_SCE_DYNEXEC = 0xfe10, // PS4 Main module 15 | ET_SCE_RELEXEC = 0xfe04, // PS4 Reloacatable PRX 16 | ET_SCE_STUBLIB = 0xfe0c, // PS4 Stub library 17 | ET_SCE_DYNAMIC = 0xfe18, // PS4 Dynamic PRX 18 | }; 19 | 20 | enum elf_DTAG_SCE 21 | { 22 | DT_SCE_FINGERPRINT = 0x61000007, 23 | DT_SCE_ORIGINAL_FILENAME = 0x61000009, 24 | DT_SCE_MODULE_INFO = 0x6100000d, 25 | DT_SCE_NEEDED_MODULE = 0x6100000f, 26 | DT_SCE_MODULE_ATTR = 0x61000011, 27 | DT_SCE_EXPORT_LIB = 0x61000013, 28 | DT_SCE_IMPORT_LIB = 0x61000015, 29 | DT_SCE_EXPORT_LIB_ATTR = 0x61000017, 30 | DT_SCE_IMPORT_LIB_ATTR = 0x61000019, 31 | DT_SCE_STUB_MODULE_NAME = 0x6100001d, 32 | DT_SCE_STUB_MODULE_VERSION = 0x6100001f, 33 | DT_SCE_STUB_LIBRARY_NAME = 0x61000021, 34 | DT_SCE_STUB_LIBRARY_VERSION = 0x61000023, 35 | DT_SCE_HASH = 0x61000025, 36 | DT_SCE_PLTGOT = 0x61000027, 37 | DT_SCE_JMPREL = 0x61000029, 38 | DT_SCE_PLTREL = 0x6100002b, 39 | DT_SCE_PLTRELSZ = 0x6100002d, 40 | DT_SCE_RELA = 0x6100002f, 41 | DT_SCE_RELASZ = 0x61000031, 42 | DT_SCE_RELAENT = 0x61000033, 43 | DT_SCE_STRTAB = 0x61000035, 44 | DT_SCE_STRSZ = 0x61000037, 45 | DT_SCE_SYMTAB = 0x61000039, 46 | DT_SCE_SYMENT = 0x6100003b, 47 | DT_SCE_HASHSZ = 0x6100003d, 48 | DT_SCE_SYMTABSZ = 0x6100003f 49 | }; 50 | 51 | enum elf_SEGTYPE_SCE 52 | { 53 | PT_SCE_DYNLIBDATA = 0x61000000, 54 | PT_SCE_PROCPARAM = 0x61000001, 55 | PT_SCE_MODULEPARAM = 0x61000002, 56 | PT_SCE_RELRO = 0x61000010, 57 | }; 58 | 59 | /* Relocation types for AMD x86-64 architecture */ 60 | #define R_X86_64_NONE 0 /* No reloc */ 61 | #define R_X86_64_64 1 /* Direct 64 bit */ 62 | #define R_X86_64_PC32 2 /* PC relative 32 bit signed */ 63 | #define R_X86_64_GOT32 3 /* 32 bit GOT entry */ 64 | #define R_X86_64_PLT32 4 /* 32 bit PLT address */ 65 | #define R_X86_64_COPY 5 /* Copy symbol at runtime */ 66 | #define R_X86_64_GLOB_DAT 6 /* Create GOT entry */ 67 | #define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */ 68 | #define R_X86_64_RELATIVE 8 /* Adjust by program base */ 69 | #define R_X86_64_GOTPCREL 9 /* 32 bit signed pc relative offset to GOT */ 70 | #define R_X86_64_32 10 /* Direct 32 bit zero extended */ 71 | #define R_X86_64_32S 11 /* Direct 32 bit sign extended */ 72 | #define R_X86_64_16 12 /* Direct 16 bit zero extended */ 73 | #define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */ 74 | #define R_X86_64_8 14 /* Direct 8 bit sign extended */ 75 | #define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */ 76 | #define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ 77 | #define R_X86_64_DTPOFF64 17 /* Offset in module's TLS block */ 78 | #define R_X86_64_TPOFF64 18 /* Offset in initial TLS block */ 79 | #define R_X86_64_TLSGD 19 /* 32 bit signed PC relative offset 80 | to two GOT entries for GD symbol */ 81 | #define R_X86_64_TLSLD 20 /* 32 bit signed PC relative offset 82 | to two GOT entries for LD symbol */ 83 | #define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ 84 | #define R_X86_64_GOTTPOFF 22 /* 32 bit signed PC relative offset 85 | to GOT entry for IE symbol */ 86 | #define R_X86_64_TPOFF32 23 /* Offset in initial TLS block */ 87 | #define R_X86_64_PC64 24 /* PC relative 64 bit */ 88 | #define R_X86_64_GOTOFF64 25 /* 64 bit offset to GOT */ 89 | #define R_X86_64_GOTPC32 26 /* 32 bit signed pc relative offset to GOT */ 90 | #define R_X86_64_GOT64 27 /* 64-bit GOT entry offset */ 91 | #define R_X86_64_GOTPCREL64 28 /* 64-bit PC relative offset to GOT entry */ 92 | #define R_X86_64_GOTPC64 29 /* 64-bit PC relative offset to GOT */ 93 | #define R_X86_64_GOTPLT64 30 /* like GOT64, says PLT entry needed */ 94 | #define R_X86_64_PLTOFF64 31 /* 64-bit GOT relative offset to PLT entry */ 95 | #define R_X86_64_SIZE32 32 /* Size of symbol plus 32-bit addend */ 96 | #define R_X86_64_SIZE64 33 /* Size of symbol plus 64-bit addend */ 97 | #define R_X86_64_GOTPC32_TLSDESC 34 /* GOT offset for TLS descriptor */ 98 | #define R_X86_64_TLSDESC_CALL 35 /* Marker for call through TLS descriptor */ 99 | #define R_X86_64_TLSDESC 36 /* TLS descriptor */ 100 | #define R_X86_64_IRELATIVE 37 /* Adjust indirectly by program base */ 101 | #define R_X86_64_RELATIVE64 38 /* 64bit adjust by program base */ 102 | #define R_X86_64_ORBIS_GOTPCREL_LOAD 40 103 | 104 | #endif 105 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015/2017 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # Visual Studio 2017 auto generated files 33 | Generated\ Files/ 34 | 35 | # MSTest test Results 36 | [Tt]est[Rr]esult*/ 37 | [Bb]uild[Ll]og.* 38 | 39 | # NUNIT 40 | *.VisualState.xml 41 | TestResult.xml 42 | 43 | # Build Results of an ATL Project 44 | [Dd]ebugPS/ 45 | [Rr]eleasePS/ 46 | dlldata.c 47 | 48 | # Benchmark Results 49 | BenchmarkDotNet.Artifacts/ 50 | 51 | # .NET Core 52 | project.lock.json 53 | project.fragment.lock.json 54 | artifacts/ 55 | **/Properties/launchSettings.json 56 | 57 | # StyleCop 58 | StyleCopReport.xml 59 | 60 | # Files built by Visual Studio 61 | *_i.c 62 | *_p.c 63 | *_i.h 64 | *.ilk 65 | *.meta 66 | *.obj 67 | *.iobj 68 | *.pch 69 | *.pdb 70 | *.ipdb 71 | *.pgc 72 | *.pgd 73 | *.rsp 74 | *.sbr 75 | *.tlb 76 | *.tli 77 | *.tlh 78 | *.tmp 79 | *.tmp_proj 80 | *.log 81 | *.vspscc 82 | *.vssscc 83 | .builds 84 | *.pidb 85 | *.svclog 86 | *.scc 87 | 88 | # Chutzpah Test files 89 | _Chutzpah* 90 | 91 | # Visual C++ cache files 92 | ipch/ 93 | *.aps 94 | *.ncb 95 | *.opendb 96 | *.opensdf 97 | *.sdf 98 | *.cachefile 99 | *.VC.db 100 | *.VC.VC.opendb 101 | 102 | # Visual Studio profiler 103 | *.psess 104 | *.vsp 105 | *.vspx 106 | *.sap 107 | 108 | # Visual Studio Trace Files 109 | *.e2e 110 | 111 | # TFS 2012 Local Workspace 112 | $tf/ 113 | 114 | # Guidance Automation Toolkit 115 | *.gpState 116 | 117 | # ReSharper is a .NET coding add-in 118 | _ReSharper*/ 119 | *.[Rr]e[Ss]harper 120 | *.DotSettings.user 121 | 122 | # JustCode is a .NET coding add-in 123 | .JustCode 124 | 125 | # TeamCity is a build add-in 126 | _TeamCity* 127 | 128 | # DotCover is a Code Coverage Tool 129 | *.dotCover 130 | 131 | # AxoCover is a Code Coverage Tool 132 | .axoCover/* 133 | !.axoCover/settings.json 134 | 135 | # Visual Studio code coverage results 136 | *.coverage 137 | *.coveragexml 138 | 139 | # NCrunch 140 | _NCrunch_* 141 | .*crunch*.local.xml 142 | nCrunchTemp_* 143 | 144 | # MightyMoose 145 | *.mm.* 146 | AutoTest.Net/ 147 | 148 | # Web workbench (sass) 149 | .sass-cache/ 150 | 151 | # Installshield output folder 152 | [Ee]xpress/ 153 | 154 | # DocProject is a documentation generator add-in 155 | DocProject/buildhelp/ 156 | DocProject/Help/*.HxT 157 | DocProject/Help/*.HxC 158 | DocProject/Help/*.hhc 159 | DocProject/Help/*.hhk 160 | DocProject/Help/*.hhp 161 | DocProject/Help/Html2 162 | DocProject/Help/html 163 | 164 | # Click-Once directory 165 | publish/ 166 | 167 | # Publish Web Output 168 | *.[Pp]ublish.xml 169 | *.azurePubxml 170 | # Note: Comment the next line if you want to checkin your web deploy settings, 171 | # but database connection strings (with potential passwords) will be unencrypted 172 | *.pubxml 173 | *.publishproj 174 | 175 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 176 | # checkin your Azure Web App publish settings, but sensitive information contained 177 | # in these scripts will be unencrypted 178 | PublishScripts/ 179 | 180 | # NuGet Packages 181 | *.nupkg 182 | # The packages folder can be ignored because of Package Restore 183 | **/[Pp]ackages/* 184 | # except build/, which is used as an MSBuild target. 185 | !**/[Pp]ackages/build/ 186 | # Uncomment if necessary however generally it will be regenerated when needed 187 | #!**/[Pp]ackages/repositories.config 188 | # NuGet v3's project.json files produces more ignorable files 189 | *.nuget.props 190 | *.nuget.targets 191 | 192 | # Microsoft Azure Build Output 193 | csx/ 194 | *.build.csdef 195 | 196 | # Microsoft Azure Emulator 197 | ecf/ 198 | rcf/ 199 | 200 | # Windows Store app package directories and files 201 | AppPackages/ 202 | BundleArtifacts/ 203 | Package.StoreAssociation.xml 204 | _pkginfo.txt 205 | *.appx 206 | 207 | # Visual Studio cache files 208 | # files ending in .cache can be ignored 209 | *.[Cc]ache 210 | # but keep track of directories ending in .cache 211 | !*.[Cc]ache/ 212 | 213 | # Others 214 | ClientBin/ 215 | ~$* 216 | *~ 217 | *.dbmdl 218 | *.dbproj.schemaview 219 | *.jfm 220 | *.pfx 221 | *.publishsettings 222 | orleans.codegen.cs 223 | 224 | # Including strong name files can present a security risk 225 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 226 | #*.snk 227 | 228 | # Since there are multiple workflows, uncomment next line to ignore bower_components 229 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 230 | #bower_components/ 231 | 232 | # RIA/Silverlight projects 233 | Generated_Code/ 234 | 235 | # Backup & report files from converting an old project file 236 | # to a newer Visual Studio version. Backup files are not needed, 237 | # because we have git ;-) 238 | _UpgradeReport_Files/ 239 | Backup*/ 240 | UpgradeLog*.XML 241 | UpgradeLog*.htm 242 | ServiceFabricBackup/ 243 | *.rptproj.bak 244 | 245 | # SQL Server files 246 | *.mdf 247 | *.ldf 248 | *.ndf 249 | 250 | # Business Intelligence projects 251 | *.rdl.data 252 | *.bim.layout 253 | *.bim_*.settings 254 | *.rptproj.rsuser 255 | 256 | # Microsoft Fakes 257 | FakesAssemblies/ 258 | 259 | # GhostDoc plugin setting file 260 | *.GhostDoc.xml 261 | 262 | # Node.js Tools for Visual Studio 263 | .ntvs_analysis.dat 264 | node_modules/ 265 | 266 | # Visual Studio 6 build log 267 | *.plg 268 | 269 | # Visual Studio 6 workspace options file 270 | *.opt 271 | 272 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 273 | *.vbw 274 | 275 | # Visual Studio LightSwitch build output 276 | **/*.HTMLClient/GeneratedArtifacts 277 | **/*.DesktopClient/GeneratedArtifacts 278 | **/*.DesktopClient/ModelManifest.xml 279 | **/*.Server/GeneratedArtifacts 280 | **/*.Server/ModelManifest.xml 281 | _Pvt_Extensions 282 | 283 | # Paket dependency manager 284 | .paket/paket.exe 285 | paket-files/ 286 | 287 | # FAKE - F# Make 288 | .fake/ 289 | 290 | # JetBrains Rider 291 | .idea/ 292 | *.sln.iml 293 | 294 | # CodeRush 295 | .cr/ 296 | 297 | # Python Tools for Visual Studio (PTVS) 298 | __pycache__/ 299 | *.pyc 300 | 301 | # Cake - Uncomment if you are using it 302 | # tools/** 303 | # !tools/packages.config 304 | 305 | # Tabs Studio 306 | *.tss 307 | 308 | # Telerik's JustMock configuration file 309 | *.jmconfig 310 | 311 | # BizTalk build output 312 | *.btp.cs 313 | *.btm.cs 314 | *.odx.cs 315 | *.xsd.cs 316 | 317 | # OpenCover UI analysis results 318 | OpenCover/ 319 | 320 | # Azure Stream Analytics local run output 321 | ASALocalRun/ 322 | 323 | # MSBuild Binary and Structured Log 324 | *.binlog 325 | 326 | # NVidia Nsight GPU debugger configuration file 327 | *.nvuser 328 | 329 | # MFractors (Xamarin productivity tool) working folder 330 | .mfractor/ 331 | -------------------------------------------------------------------------------- /belf/utils.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "elfr_sce.h" 4 | 5 | #include "utils.h" 6 | 7 | qstring ph_type_to_string(uint32 p_type) 8 | { 9 | switch (p_type) 10 | { 11 | case PT_NULL: return "PT_NULL"; 12 | case PT_LOAD: return "PT_LOAD"; 13 | case PT_DYNAMIC: return "PT_DYNAMIC"; 14 | case PT_INTERP: return "PT_INTERP"; 15 | case PT_NOTE: return "PT_NOTE"; 16 | case PT_SHLIB: return "PT_SHLIB"; 17 | case PT_PHDR: return "PT_PHDR"; 18 | case PT_TLS: return "PT_TLS"; 19 | case PT_LOOS: return "PT_LOOS"; 20 | case PT_HIOS: return "PT_HIOS"; 21 | case PT_LOPROC: return "PT_LOPROC"; 22 | case PT_HIPROC: return "PT_HIPROC"; 23 | 24 | case PT_PAX_FLAGS: return "PT_PAX_FLAGS"; 25 | 26 | case PT_GNU_EH_FRAME: return "PT_GNU_EH_FRAME"; 27 | case PT_GNU_STACK: return "PT_GNU_STACK"; 28 | case PT_GNU_RELRO: return "PT_GNU_RELRO"; 29 | 30 | case PT_SUNW_UNWIND: return "PT_SUNW_UNWIND / PT_SUNW_EH_FRAME"; 31 | case PT_SUNWBSS: return "PT_SUNWBSS"; 32 | case PT_SUNWSTACK: return "PT_SUNWSTACK"; 33 | case PT_SUNWDTRACE: return "PT_SUNWDTRACE"; 34 | case PT_SUNWCAP: return "PT_SUNWCAP"; 35 | 36 | case PT_SCE_DYNLIBDATA: return "PT_SCE_DYNLIBDATA"; 37 | case PT_SCE_PROCPARAM: return "PT_SCE_PROCPARAM"; 38 | case PT_SCE_MODULEPARAM: return "PT_SCE_MODULEPARAM"; 39 | case PT_SCE_RELRO: return "PT_SCE_RELRO"; 40 | } 41 | 42 | qstring ret; 43 | ret.sprnt("UNK_%x", p_type); 44 | return ret; 45 | } 46 | 47 | qstring dyntag_to_string(uint64 tag) 48 | { 49 | switch (tag) 50 | { 51 | case DT_NULL: return "DT_NULL"; 52 | case DT_NEEDED: return "DT_NEEDED"; 53 | case DT_PLTRELSZ: return "DT_PLTRELSZ"; 54 | case DT_PLTGOT: return "DT_PLTGOT"; 55 | case DT_HASH: return "DT_HASH"; 56 | case DT_STRTAB: return "DT_STRTAB"; 57 | case DT_SYMTAB: return "DT_SYMTAB"; 58 | case DT_RELA: return "DT_RELA"; 59 | case DT_RELASZ: return "DT_RELASZ"; 60 | case DT_RELAENT: return "DT_RELAENT"; 61 | case DT_STRSZ: return "DT_STRSZ"; 62 | case DT_SYMENT: return "DT_SYMENT"; 63 | case DT_INIT: return "DT_INIT"; 64 | case DT_FINI: return "DT_FINI"; 65 | case DT_SONAME: return "DT_SONAME"; 66 | case DT_RPATH: return "DT_RPATH"; 67 | case DT_SYMBOLIC: return "DT_SYMBOLIC"; 68 | case DT_REL: return "DT_REL"; 69 | case DT_RELSZ: return "DT_RELSZ"; 70 | case DT_RELENT: return "DT_RELENT"; 71 | case DT_PLTREL: return "DT_PLTREL"; 72 | case DT_DEBUG: return "DT_DEBUG"; 73 | case DT_TEXTREL: return "DT_TEXTREL"; 74 | case DT_JMPREL: return "DT_JMPREL"; 75 | case DT_BIND_NOW: return "DT_BIND_NOW"; 76 | case DT_INIT_ARRAY: return "DT_INIT_ARRAY"; 77 | case DT_FINI_ARRAY: return "DT_FINI_ARRAY"; 78 | case DT_INIT_ARRAYSZ: return "DT_INIT_ARRAYSZ"; 79 | case DT_FINI_ARRAYSZ: return "DT_FINI_ARRAYSZ"; 80 | case DT_RUNPATH: return "DT_RUNPATH"; 81 | case DT_FLAGS: return "DT_FLAGS"; 82 | case DT_ENCODING: return "DT_ENCODING"; 83 | case DT_PREINIT_ARRAY: return "DT_PREINIT_ARRAY"; 84 | case DT_PREINIT_ARRAYSZ: return "DT_PREINIT_ARRAYSZ"; 85 | case DT_LOOS: return "DT_LOOS"; 86 | case DT_HIOS: return "DT_HIOS/DT_VERNEEDNUM"; 87 | case DT_SUNW_AUXILIARY: return "DT_SUNW_AUXILIARY"; 88 | case DT_SUNW_RTLDINF: return "DT_SUNW_RTLDINF/DT_SUNW_FILTER"; 89 | case DT_SUNW_CAP: return "DT_SUNW_CAP"; 90 | case DT_SUNW_SYMTAB: return "DT_SUNW_SYMTAB"; 91 | case DT_SUNW_SYMSZ: return "DT_SUNW_SYMSZ"; 92 | case DT_SUNW_ENCODING: return "DT_SUNW_ENCODING/DT_SUNW_SORTENT"; 93 | case DT_SUNW_SYMSORT: return "DT_SUNW_SYMSORT"; 94 | case DT_SUNW_SYMSORTSZ: return "DT_SUNW_SYMSORTSZ"; 95 | case DT_SUNW_TLSSORT: return "DT_SUNW_TLSSORT"; 96 | case DT_SUNW_TLSSORTSZ: return "DT_SUNW_TLSSORTSZ"; 97 | case DT_SUNW_CAPINFO: return "DT_SUNW_CAPINFO"; 98 | case DT_SUNW_STRPAD: return "DT_SUNW_STRPAD"; 99 | case DT_SUNW_CAPCHAIN: return "DT_SUNW_CAPCHAIN"; 100 | case DT_SUNW_LDMACH: return "DT_SUNW_LDMACH"; 101 | case DT_SUNW_CAPCHAINENT: return "DT_SUNW_CAPCHAINENT"; 102 | case DT_SUNW_CAPCHAINSZ: return "DT_SUNW_CAPCHAINSZ"; 103 | case DT_SUNW_PARENT: return "DT_SUNW_PARENT"; 104 | case DT_SUNW_ASLR: return "DT_SUNW_ASLR"; 105 | case DT_SUNW_RELAX: return "DT_SUNW_RELAX"; 106 | case DT_SUNW_NXHEAP: return "DT_SUNW_NXHEAP"; 107 | case DT_SUNW_NXSTACK: return "DT_SUNW_NXSTACK"; 108 | case DT_VALRNGLO: return "DT_VALRNGLO"; 109 | case DT_GNU_PRELINKED: return "DT_GNU_PRELINKED"; 110 | case DT_GNU_CONFLICTSZ: return "DT_GNU_CONFLICTSZ"; 111 | case DT_GNU_LIBLISTSZ: return "DT_GNU_LIBLISTSZ"; 112 | case DT_CHECKSUM: return "DT_CHECKSUM"; 113 | case DT_PLTPADSZ: return "DT_PLTPADSZ"; 114 | case DT_MOVEENT: return "DT_MOVEENT"; 115 | case DT_MOVESZ: return "DT_MOVESZ"; 116 | case DT_FEATURE: return "DT_FEATURE"; 117 | case DT_POSFLAG_1: return "DT_POSFLAG_1"; 118 | case DT_SYMINSZ: return "DT_SYMINSZ"; 119 | case DT_SYMINENT: return "DT_SYMINENT/DT_VALRNGHI"; 120 | case DT_ADDRRNGLO: return "DT_ADDRRNGLO"; 121 | case DT_GNU_HASH: return "DT_GNU_HASH"; 122 | case DT_TLSDESC_PLT: return "DT_TLSDESC_PLT"; 123 | case DT_TLSDESC_GOT: return "DT_TLSDESC_GOT"; 124 | case DT_GNU_CONFLICT: return "DT_GNU_CONFLICT"; 125 | case DT_GNU_LIBLIST: return "DT_GNU_LIBLIST"; 126 | case DT_CONFIG: return "DT_CONFIG"; 127 | case DT_DEPAUDIT: return "DT_DEPAUDIT"; 128 | case DT_AUDIT: return "DT_AUDIT"; 129 | case DT_PLTPAD: return "DT_PLTPAD"; 130 | case DT_MOVETAB: return "DT_MOVETAB"; 131 | case DT_SYMINFO: return "DT_SYMINFO/DT_ADDRRNGHI"; 132 | case DT_RELACOUNT: return "DT_RELACOUNT"; 133 | case DT_RELCOUNT: return "DT_RELCOUNT"; 134 | case DT_FLAGS_1: return "DT_FLAGS_1"; 135 | case DT_VERDEF: return "DT_VERDEF"; 136 | case DT_VERDEFNUM: return "DT_VERDEFNUM"; 137 | case DT_VERNEED: return "DT_VERNEED"; 138 | case DT_VERSYM: return "DT_VERSYM"; 139 | case DT_LOPROC: return "DT_LOPROC"; 140 | case DT_HIPROC: return "DT_HIPROC"; 141 | case DT_AUXILIARY: return "DT_AUXILIARY/DT_FILTER"; 142 | case DT_USED: return "DT_USED"; 143 | 144 | case DT_SCE_FINGERPRINT: return "DT_SCE_FINGERPRINT"; 145 | case DT_SCE_ORIGINAL_FILENAME: return "DT_SCE_ORIGINAL_FILENAME"; 146 | case DT_SCE_MODULE_INFO: return "DT_SCE_MODULE_INFO"; 147 | case DT_SCE_NEEDED_MODULE: return "DT_SCE_NEEDED_MODULE"; 148 | case DT_SCE_MODULE_ATTR: return "DT_SCE_MODULE_ATTR"; 149 | case DT_SCE_EXPORT_LIB: return "DT_SCE_EXPORT_LIB"; 150 | case DT_SCE_IMPORT_LIB: return "DT_SCE_IMPORT_LIB"; 151 | case DT_SCE_EXPORT_LIB_ATTR: return "DT_SCE_EXPORT_LIB_ATTR"; 152 | case DT_SCE_IMPORT_LIB_ATTR: return "DT_SCE_IMPORT_LIB_ATTR"; 153 | case DT_SCE_STUB_MODULE_NAME: return "DT_SCE_STUB_MODULE_NAME"; 154 | case DT_SCE_STUB_MODULE_VERSION: return "DT_SCE_STUB_MODULE_VERSION"; 155 | case DT_SCE_STUB_LIBRARY_NAME: return "DT_SCE_STUB_LIBRARY_NAME"; 156 | case DT_SCE_STUB_LIBRARY_VERSION: return "DT_SCE_STUB_LIBRARY_VERSION"; 157 | case DT_SCE_HASH: return "DT_SCE_HASH"; 158 | case DT_SCE_PLTGOT: return "DT_SCE_PLTGOT"; 159 | case DT_SCE_JMPREL: return "DT_SCE_JMPREL"; 160 | case DT_SCE_PLTREL: return "DT_SCE_PLTREL"; 161 | case DT_SCE_PLTRELSZ: return "DT_SCE_PLTRELSZ"; 162 | case DT_SCE_RELA: return "DT_SCE_RELA"; 163 | case DT_SCE_RELASZ: return "DT_SCE_RELASZ"; 164 | case DT_SCE_RELAENT: return "DT_SCE_RELAENT"; 165 | case DT_SCE_STRTAB: return "DT_SCE_STRTAB"; 166 | case DT_SCE_STRSZ: return "DT_SCE_STRSZ"; 167 | case DT_SCE_SYMTAB: return "DT_SCE_SYMTAB"; 168 | case DT_SCE_SYMENT: return "DT_SCE_SYMENT"; 169 | case DT_SCE_HASHSZ: return "DT_SCE_HASHSZ"; 170 | case DT_SCE_SYMTABSZ: return "DT_SCE_SYMTABSZ"; 171 | } 172 | 173 | qstring ret; 174 | ret.sprnt("UNK_%llx", tag); 175 | return ret; 176 | } 177 | 178 | int decode_base64(const char *str, int *a2) 179 | { 180 | char chr; // dl@1 181 | int v3; // rcx@1 182 | const char *v4; // rdi@2 183 | int v5; // rcx@3 184 | int result; // rax@11 185 | 186 | chr = *str; 187 | v3 = 0LL; 188 | if (*str) { 189 | v4 = str + 1; 190 | v3 = 0LL; 191 | do { 192 | v5 = v3 << 6; 193 | if ((unsigned __int8)(chr - 0x61) > 0x19u) { 194 | if ((unsigned __int8)(chr - 0x41) > 0x19u) { 195 | if ((unsigned __int8)(chr - 0x30) > 9u) { 196 | if (chr == '-') 197 | v3 = v5 | 0x3F; 198 | else { 199 | result = 22LL; 200 | if (chr != '+') 201 | return result; 202 | v3 = v5 | 0x3E; 203 | } 204 | } 205 | else { 206 | v3 = chr + (v5 | 4); 207 | } 208 | } 209 | else { 210 | v3 = v5 + chr - 0x41; 211 | } 212 | } 213 | else { 214 | v3 = v5 + chr - 0x47; 215 | } 216 | chr = *v4++; 217 | } while (chr); 218 | } 219 | *a2 = v3; 220 | return 0LL; 221 | } -------------------------------------------------------------------------------- /belf/belf.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {2D75A06D-1D61-4A5A-BC67-77C838919697} 24 | Win32Proj 25 | belf 26 | 10.0.17134.0 27 | 28 | 29 | 30 | DynamicLibrary 31 | true 32 | v141 33 | Unicode 34 | 35 | 36 | DynamicLibrary 37 | false 38 | v141 39 | true 40 | Unicode 41 | 42 | 43 | DynamicLibrary 44 | true 45 | v141 46 | MultiByte 47 | 48 | 49 | DynamicLibrary 50 | false 51 | v141 52 | true 53 | MultiByte 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | C:\PS4\7.1.180227\idasdk71\ldr\elf;C:\PS4\7.1.180227\idasdk71\include;$(IncludePath) 76 | C:\PS4\7.1.180227\idasdk71\lib\x64_win_vc_64;$(LibraryPath) 77 | 78 | 79 | true 80 | $(ProjectName)64 81 | C:\PS4\7.1.180227\idasdk71\ldr\elf;C:\PS4\7.1.180227\idasdk71\include;$(IncludePath) 82 | C:\PS4\7.1.180227\idasdk71\lib\x64_win_vc_64;$(LibraryPath) 83 | 84 | 85 | false 86 | C:\PS4\7.1.180227\idasdk71\ldr\elf;C:\PS4\7.1.180227\idasdk71\include;$(IncludePath) 87 | C:\PS4\7.1.180227\idasdk71\lib\x64_win_vc_64;$(LibraryPath) 88 | 89 | 90 | false 91 | $(ProjectName)64 92 | C:\PS4\7.1.180227\idasdk71\ldr\elf;C:\PS4\7.1.180227\idasdk71\include;$(IncludePath) 93 | C:\PS4\7.1.180227\idasdk71\lib\x64_win_vc_64;$(LibraryPath) 94 | 95 | 96 | 97 | NotUsing 98 | Level3 99 | Disabled 100 | true 101 | WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 102 | true 103 | 104 | 105 | Windows 106 | true 107 | ida.lib;%(AdditionalDependencies) 108 | 109 | 110 | 111 | 112 | NotUsing 113 | Level3 114 | Disabled 115 | true 116 | __NT__;__X64__;__EA64__;__IDP__;USE_STANDARD_FILE_FUNCTIONS;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 117 | true 118 | 119 | 120 | Windows 121 | DebugFull 122 | ida.lib;Shlwapi.lib;%(AdditionalDependencies) 123 | 124 | 125 | 126 | 127 | NotUsing 128 | Level3 129 | MaxSpeed 130 | true 131 | true 132 | true 133 | WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 134 | true 135 | 136 | 137 | Windows 138 | true 139 | true 140 | true 141 | ida.lib;%(AdditionalDependencies) 142 | 143 | 144 | 145 | 146 | NotUsing 147 | Level3 148 | MaxSpeed 149 | true 150 | true 151 | true 152 | __NT__;__X64__;__EA64__;__IDP__;USE_STANDARD_FILE_FUNCTIONS;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 153 | true 154 | 155 | 156 | Windows 157 | true 158 | true 159 | true 160 | ida.lib;Shlwapi.lib;%(AdditionalDependencies) 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | -------------------------------------------------------------------------------- /belf/belf_loader.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "elfr_sce.h" 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "utils.h" 13 | #include "dynlib.h" 14 | 15 | static bool accept_handler(const reader_t &reader, reader_t::errcode_t code, ...) 16 | { 17 | return true; 18 | } 19 | 20 | bool is_ps4_elf(reader_t &reader) 21 | { 22 | auto filetype = reader.get_header().e_type; 23 | 24 | return filetype == ET_SCE_EXEC || filetype == ET_SCE_DYNEXEC || 25 | filetype == ET_SCE_RELEXEC || filetype == ET_SCE_STUBLIB || filetype == ET_SCE_DYNAMIC; 26 | } 27 | 28 | int idaapi elf_accept_file(qstring *fileformatname, qstring *processor, linput_t *li, const char *filename) 29 | { 30 | reader_t reader(li); 31 | 32 | reader.set_handler(accept_handler); 33 | 34 | if ( 35 | reader.read_ident() && 36 | reader.read_header() && 37 | reader.get_header().e_machine == EM_X86_64 && 38 | is_ps4_elf(reader) 39 | ) 40 | { 41 | fileformatname->sprnt("Balika011's ELF%s for %s (%s)", reader.is_64() ? "64" : "", 42 | reader.machine_name_str(), reader.file_type_str()); 43 | 44 | processor->sprnt("metapc"); 45 | 46 | return 1; 47 | } 48 | 49 | return 0; 50 | } 51 | 52 | static bool load_handler(const reader_t &reader, reader_t::errcode_t code, ...) 53 | { 54 | return true; 55 | } 56 | 57 | uint16 load_elf(reader_t *reader) 58 | { 59 | reader->set_handler(load_handler); 60 | 61 | if (!reader->read_ident() || !reader->read_header()) 62 | loader_failure("Failed reading ELF header"); 63 | 64 | if (reader->is_msb()) 65 | inf.lflags |= LFLG_MSF; 66 | else 67 | inf.lflags &= ~LFLG_MSF; 68 | 69 | while (true) 70 | { 71 | inf.lflags |= LFLG_PC_FLAT; 72 | if (reader->get_header().e_machine == EM_PPC64 73 | || reader->get_header().e_machine == EM_IA64 74 | || reader->get_header().e_machine == EM_X86_64 75 | || reader->get_header().e_machine == EM_AARCH64 76 | || reader->get_header().e_machine == EM_ALPHA) 77 | { 78 | inf.lflags |= LFLG_PC_FLAT | LFLG_64BIT; 79 | inf.cc.cm &= ~2u; 80 | inf.cc.cm |= 1u; 81 | } 82 | 83 | const char *procname = "metapc"; 84 | proc_def_t *pd = nullptr; 85 | int ret = ph.notify(processor_t::ev_loader_elf_machine, reader->get_linput(), reader->get_header().e_machine, &procname, &pd); 86 | if (!ret || ret == reader->get_header().e_machine) 87 | break; 88 | reader->get_header().e_machine = ret; 89 | } 90 | 91 | set_processor_type("metapc", SETPROC_LOADER); 92 | 93 | if (reader->is_msb()) 94 | inf.lflags |= LFLG_MSF; 95 | else 96 | inf.lflags &= ~LFLG_MSF; 97 | 98 | if (reader->is_64()) 99 | { 100 | inf.lflags |= LFLG_PC_FLAT | LFLG_64BIT; 101 | inf.cc.cm &= ~2u; 102 | inf.cc.cm |= 1u; 103 | } 104 | 105 | // TODO: Add PS4 support? 106 | 107 | if (reader->get_header().e_type == ET_DYN) 108 | { 109 | inf.lflags |= LFLG_IS_DLL; 110 | } 111 | 112 | return reader->get_header().e_machine; 113 | } 114 | 115 | idaman void ida_export add_test_feature(const char *feature); 116 | 117 | bool __fastcall elf_set_compiler(__int16 machine, char flags, char osabi) 118 | { 119 | const char *abiname = ""; 120 | 121 | switch (machine) 122 | { 123 | case EM_PPC64: 124 | if (osabi == ELFOSABI_CELLOSLV2) 125 | { 126 | abiname = "celloslv2"; 127 | break; 128 | } 129 | if ((flags & 3) == 2) 130 | { 131 | abiname = "elfv2"; 132 | add_test_feature("elfv2"); 133 | break; 134 | } 135 | return false; 136 | 137 | case EM_PPC: 138 | abiname = "sysv"; 139 | break; 140 | 141 | case EM_ARM: 142 | case EM_AARCH64: 143 | abiname = "eabi"; 144 | break; 145 | 146 | case EM_X86_64: 147 | if (osabi == ELFOSABI_NACL) 148 | { 149 | abiname = "nacl"; 150 | false; 151 | } 152 | 153 | return 0; 154 | } 155 | 156 | compiler_info_t cc; 157 | cc.id = 0; 158 | return set_compiler(cc, 4i64, abiname); 159 | } 160 | 161 | void load_jmprel(reader_t &reader, elf_phdr_t &dyndata, dynamic_info_t::entry_t &jmprel_entry, elf_sym_t *&symtab, char *&strtab, DynLib &dynlib) 162 | { 163 | elf_rela_t *jmprel = new elf_rela_t[jmprel_entry.size / sizeof(elf_rela_t)]; 164 | reader.seek(dyndata.p_offset + jmprel_entry.addr); 165 | if (reader.safe_read(jmprel, jmprel_entry.size, false) != 0) 166 | loader_failure("failed to read jmprel"); 167 | 168 | for (size_t i = 0; i < jmprel_entry.size / sizeof(elf_rela_t); i++) 169 | { 170 | int type = reader.rel_info_type(jmprel[i]); 171 | int idx = reader.rel_info_index(jmprel[i]); 172 | 173 | if (type != R_X86_64_JUMP_SLOT) { 174 | msg("Unexpected reloc type %i for jump slot %i\n", type, i); 175 | continue; 176 | } 177 | 178 | if (idx >= jmprel_entry.size / sizeof(elf_sym_t)) { 179 | msg("dyninfo.symtab().size: %x\n", jmprel_entry.size); 180 | msg("Invalid symbol index %i for relocation %i\n", idx, i); 181 | continue; 182 | } 183 | 184 | if (symtab[idx].st_name >= jmprel_entry.size) { 185 | msg("Invalid symbol string offset %x of symbol %i for relocation %i\n", symtab[idx].st_name, idx, i); 186 | continue; 187 | } 188 | 189 | qstring name = &strtab[symtab[idx].st_name]; 190 | const char* module_name = ""; 191 | 192 | if (dynlib.isObfuscated(name.c_str())) 193 | { 194 | uint32 modidx = dynlib.lookup(name.c_str()); 195 | if (modidx != -1) 196 | module_name = &strtab[modidx]; 197 | 198 | qstring deobf_name = dynlib.deobfuscate(module_name, name); 199 | if (deobf_name != "") 200 | name = deobf_name; 201 | } 202 | 203 | qstring import_name; 204 | import_name.sprnt(FUNC_IMPORT_PREFIX "%s", name.c_str()); 205 | force_name(jmprel[i].r_offset, import_name.c_str()); 206 | 207 | netnode import_node; 208 | netnode_check(&import_node, module_name, 0, true); //"$ IDALDR node for ids loading $" 209 | netnode_supset(import_node, jmprel[i].r_offset, name.c_str(), 0, 339); 210 | import_module(module_name, 0, import_node, 0, "linux"); 211 | } 212 | delete[] jmprel; 213 | } 214 | 215 | void load_symtab(dynamic_info_t::entry_t &symtab_entry, elf_sym_t *&symtab, char *&strtab, DynLib &dynlib) 216 | { 217 | for (int i = 0; i < symtab_entry.size / sizeof(elf_sym_t); i++) 218 | { 219 | if (symtab[i].st_value == 0) 220 | continue; 221 | 222 | qstring name = &strtab[symtab[i].st_name]; 223 | const char* module_name = ""; 224 | 225 | if (dynlib.isObfuscated(name.c_str())) 226 | { 227 | uint32 modidx = dynlib.lookup(name.c_str()); 228 | if (modidx != -1) 229 | module_name = &strtab[modidx]; 230 | 231 | qstring deobf_name = dynlib.deobfuscate(module_name, name); 232 | if (deobf_name != "") 233 | name = deobf_name; 234 | } 235 | 236 | if (ELF_ST_TYPE(symtab[i].st_info) == STT_FUNC || ELF_ST_TYPE(symtab[i].st_info) == STT_GNU_IFUNC) 237 | { 238 | add_entry(symtab[i].st_value, symtab[i].st_value, name.c_str(), true); 239 | } 240 | else 241 | { 242 | force_name(symtab[i].st_value, name.c_str()); 243 | } 244 | } 245 | } 246 | 247 | void load_rela(reader_t &reader, elf_phdr_t &dyndata, dynamic_info_t::entry_t &rela_entry) 248 | { 249 | elf_rela_t *rela = new elf_rela_t[rela_entry.size / sizeof(elf_rela_t)]; 250 | reader.seek(dyndata.p_offset + rela_entry.addr); 251 | if (reader.safe_read(rela, rela_entry.size, false) != 0) 252 | loader_failure("failed to read rela"); 253 | 254 | for (int i = 0; i < rela_entry.size / sizeof(elf_sym_t); i++) 255 | { 256 | int type = reader.rel_info_type(rela[i]); 257 | int idx = reader.rel_info_index(rela[i]); 258 | 259 | if (type != R_X86_64_RELATIVE) { 260 | msg("Unexpected reloc type %i for rela %i at offset 0x%x\n", type, i, rela[i].r_offset); 261 | continue; 262 | } 263 | 264 | put_qword(rela[i].r_offset, rela[i].r_addend); 265 | } 266 | 267 | delete[] rela; 268 | } 269 | 270 | void createSegment(const char *name, uint32 flags, uchar bitness, uchar type, ea_t start, ea_t end) 271 | { 272 | static sel_t g_sel = 0; 273 | 274 | segment_t s; 275 | memset(&s, 0, sizeof(segment_t)); 276 | s.color = -1; 277 | s.align = 1; 278 | s.comb = scPub; 279 | s.perm = 0; 280 | if (flags & PF_R) 281 | s.perm |= SEGPERM_READ; 282 | if (flags & PF_W) 283 | s.perm |= SEGPERM_WRITE; 284 | if (flags & PF_X) 285 | s.perm |= SEGPERM_EXEC; 286 | s.bitness = bitness; 287 | s.sel = g_sel++; 288 | s.type = type; 289 | s.start_ea = start; 290 | s.end_ea = end; 291 | 292 | if (!add_segm_ex(&s, name, 0, ADDSEG_SPARSE)) 293 | loader_failure("Could not create segment '%s' at %a..%a", name, s.start_ea, s.end_ea, s.start_ea); 294 | } 295 | 296 | void idaapi elf_load_file(linput_t *li, ushort neflags, const char *fileformatname) 297 | { 298 | #ifdef _DEBUG 299 | debug = IDA_DEBUG_ALWAYS; 300 | #endif 301 | 302 | char db[QMAXPATH]; 303 | if (getsysfile(db, QMAXPATH, "dynlib.xml", LDR_SUBDIR) == NULL) 304 | loader_failure("Could not find dynlib database file."); 305 | 306 | DynLib dynlib(db); 307 | 308 | reader_t reader(li); 309 | 310 | uint16 machine = load_elf(&reader); 311 | elf_set_compiler(machine, reader.get_header().e_flags, reader.get_header().e_ident.osabi); 312 | 313 | inf.baseaddr = 0; 314 | inf.specsegs = reader.is_64() ? 8 : 4; 315 | 316 | if (reader.get_header().e_phoff) 317 | add_test_feature("pht"); 318 | 319 | if (reader.get_header().e_shoff) 320 | add_test_feature("sht"); 321 | 322 | if (!reader.get_header().e_phoff) 323 | loader_failure("Missing program headers"); 324 | 325 | if (!reader.read_program_headers()) 326 | loader_failure("Failed reading program headers"); 327 | 328 | set_imagebase(reader.pheaders.get_image_base()); 329 | 330 | elf_phdr_t dyndata; 331 | 332 | for (int i = 0; i < reader.pheaders.size(); i++) 333 | { 334 | elf_phdr_t *phdr = reader.pheaders.get(i); 335 | 336 | switch (phdr->p_type) 337 | { 338 | case PT_LOAD: 339 | { 340 | const char *name = phdr->p_flags & PF_X ? "CODE" : "DATA"; 341 | uchar type = phdr->p_flags & PF_X ? SEG_CODE : SEG_DATA; 342 | 343 | createSegment(name, phdr->p_flags, reader.get_seg_bitness(), type, phdr->p_vaddr, phdr->p_vaddr + phdr->p_memsz); 344 | 345 | file2base(li, phdr->p_offset, phdr->p_vaddr, phdr->p_vaddr + phdr->p_filesz, FILEREG_PATCHABLE); 346 | break; 347 | } 348 | case PT_SCE_RELRO: 349 | { 350 | createSegment(".relro", phdr->p_flags, reader.get_seg_bitness(), SEG_XTRN, phdr->p_vaddr, phdr->p_vaddr + phdr->p_memsz); 351 | 352 | file2base(li, phdr->p_offset, phdr->p_vaddr, phdr->p_vaddr + phdr->p_filesz, FILEREG_PATCHABLE); 353 | break; 354 | } 355 | case PT_GNU_EH_FRAME: 356 | { 357 | createSegment(".eh_frame", phdr->p_flags, reader.get_seg_bitness(), SEG_DATA, phdr->p_vaddr, phdr->p_vaddr + phdr->p_memsz); 358 | 359 | file2base(li, phdr->p_offset, phdr->p_vaddr, phdr->p_vaddr + phdr->p_filesz, FILEREG_PATCHABLE); 360 | break; 361 | } 362 | case PT_SCE_DYNLIBDATA: 363 | dyndata = *phdr; 364 | break; 365 | 366 | default: 367 | msg("pheader!\n"); 368 | msg(" p_type: %s\n", ph_type_to_string(phdr->p_type).c_str()); 369 | msg(" p_flags: 0x%x\n", phdr->p_flags); 370 | msg(" p_offset: 0x%llx\n", phdr->p_offset); 371 | msg(" p_vaddr: 0x%llx\n", phdr->p_vaddr); 372 | msg(" p_paddr: 0x%llx\n", phdr->p_paddr); 373 | msg(" p_filesz: 0x%llx\n", phdr->p_filesz); 374 | msg(" p_memsz: 0x%llx\n", phdr->p_memsz); 375 | msg(" p_align: 0x%llx\n", phdr->p_align); 376 | } 377 | } 378 | 379 | inf.start_ip = get_imagebase() + reader.get_header().e_entry; 380 | inf.start_cs = getseg(inf.start_ip)->sel; 381 | msg("entry point: 0x%x\n", reader.get_header().e_entry); 382 | 383 | reader_t::dyninfo_tags_t dyninfo_tags; 384 | dynamic_info_t dyninfo; 385 | if (!reader.read_dynamic_info_tags(&dyninfo_tags, reader.pheaders.get_dynamic_linking_tables_info()) || 386 | !reader.parse_dynamic_info(&dyninfo, dyninfo_tags)) 387 | loader_failure("Failed to read / parse dynamic info"); 388 | 389 | if (dyninfo.strtab().addr + dyninfo.strtab().size > dyndata.p_filesz) 390 | loader_failure("strtab is out of dyndata"); 391 | 392 | char *strtab = new char[dyninfo.strtab().size]; 393 | reader.seek(dyndata.p_offset + dyninfo.strtab().addr); 394 | if (reader.safe_read(strtab, dyninfo.strtab().size, false) != 0) 395 | loader_failure("failed to read strtab"); 396 | 397 | elf_sym_t *symtab = new elf_sym_t[dyninfo.symtab().size / sizeof(elf_sym_t)]; 398 | reader.seek(dyndata.p_offset + dyninfo.symtab().addr); 399 | if (reader.safe_read(symtab, dyninfo.symtab().size, false) != 0) 400 | loader_failure("failed to read symtab"); 401 | 402 | for (auto dyn = dyninfo_tags.begin(); dyn != dyninfo_tags.end(); ++dyn) 403 | { 404 | switch (dyn->d_tag) 405 | { 406 | case DT_INIT: add_entry(reader.get_load_bias() + dyn->d_un, reader.get_load_bias() + dyn->d_un, ".init_proc", true); break; 407 | case DT_FINI: add_entry(reader.get_load_bias() + dyn->d_un, reader.get_load_bias() + dyn->d_un, ".term_proc", true); break; 408 | case DT_NEEDED: msg("DT_NEEDED: %s\n", &strtab[dyn->d_un]); break; 409 | case DT_SCE_NEEDED_MODULE: 410 | { 411 | uint32 mid = dyn->d_un >> 48; 412 | uint32 mnameidx = dyn->d_un & 0xFFFFFFFF; 413 | msg("DT_SCE_NEEDED_MODULE: %x:%s\n", mid, &strtab[mnameidx]); 414 | 415 | dynlib.addModule(mid, mnameidx); 416 | break; 417 | } 418 | case DT_SCE_IMPORT_LIB: 419 | case DT_SCE_EXPORT_LIB: 420 | msg("PORT: tag: %08x \t un: %08llx\n", dyn->d_tag, dyndata.p_offset + dyn->d_un); break; 421 | case DT_SCE_IMPORT_LIB_ATTR: 422 | case DT_SCE_EXPORT_LIB_ATTR: 423 | msg("PORT: tag: %08x \t un: %08llx\n", dyn->d_tag, dyn->d_un); break; 424 | case DT_SCE_MODULE_INFO: 425 | dynlib.setSelfModuleStrIndex(dyn->d_un & 0xFFFFFFFF); 426 | } 427 | } 428 | 429 | load_jmprel(reader, dyndata, dyninfo.jmprel(), symtab, strtab, dynlib); 430 | 431 | load_symtab(dyninfo.symtab(), symtab, strtab, dynlib); 432 | 433 | load_rela(reader, dyndata, dyninfo.rela()); 434 | 435 | delete[] symtab; 436 | delete[] strtab; 437 | 438 | #ifdef _DEBUG 439 | debug = 0; 440 | #endif 441 | } 442 | 443 | int idaapi elf_save_file(FILE *fp, const char *fileformatname) 444 | { 445 | return 0; 446 | } 447 | 448 | extern "C" __declspec(dllexport) loader_t LDSC = { 449 | IDP_INTERFACE_VERSION, 450 | 0, 451 | elf_accept_file, 452 | elf_load_file, 453 | elf_save_file, 454 | nullptr, 455 | nullptr 456 | }; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /belf/reader.cpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef ELF_READER_CPP 3 | #define ELF_READER_CPP 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include "elfr_sce.h" 23 | #ifdef BUILD_LOADER 24 | #include "../idaldr.h" 25 | #include "../../module/arm/notify_codes.hpp" 26 | #endif 27 | #include "utils.h" 28 | 29 | //---------------------------------------------------------------------------- 30 | ssize_t reader_t::prepare_error_string( 31 | char *buf, 32 | size_t bufsize, 33 | reader_t::errcode_t code, 34 | va_list va) const 35 | { 36 | int len; 37 | switch ( code ) 38 | { 39 | case BAD_CLASS: 40 | { 41 | int eclass = va_arg(va, int); 42 | len = qsnprintf(buf, bufsize, 43 | "Unknown ELF class %d (should be %d for 32-bit, %d for 64-bit)", 44 | eclass, 45 | ELFCLASS32, 46 | ELFCLASS64); 47 | } 48 | break; 49 | case BAD_ENDIANNESS: 50 | { 51 | int endian = va_arg(va, int); 52 | if ( endian != ELFDATA2LSB && endian != ELFDATA2MSB ) 53 | len = qsnprintf(buf, bufsize, 54 | "Unknown ELF byte sex %d (should be %d for LSB, %d for MSB)", 55 | endian, 56 | ELFDATA2LSB, 57 | ELFDATA2MSB); 58 | else 59 | len = qsnprintf(buf, bufsize, 60 | "Bad ELF byte sex %d for the indicated machine", 61 | endian); 62 | } 63 | break; 64 | case BAD_EHSIZE: 65 | { 66 | int sz = va_arg(va, int); 67 | int fb = va_arg(va, int); 68 | len = qsnprintf(buf, bufsize, 69 | "The ELF header entry size is invalid (%d, expected %d)", 70 | sz, fb); 71 | } 72 | break; 73 | case BAD_PHENTSIZE: 74 | { 75 | int sz = va_arg(va, int); 76 | int fb = va_arg(va, int); 77 | len = qsnprintf(buf, bufsize, 78 | "PHT entry size is invalid: %d. Falling back to %d", 79 | sz, fb); 80 | } 81 | break; 82 | case BAD_PHLOC: 83 | len = qstpncpy(buf, "The PHT table size or offset is invalid", bufsize) - buf; 84 | break; 85 | case BAD_SHENTSIZE: 86 | len = qstpncpy(buf, "The SHT entry size is invalid", bufsize) - buf; 87 | break; 88 | case BAD_SHLOC: 89 | len = qstpncpy(buf, "SHT table size or offset is invalid", bufsize) - buf; 90 | break; 91 | case BAD_DYN_PLT_TYPE: 92 | len = qsnprintf(buf, bufsize, "Bad DT_PLTREL value (%d)", va_arg(va, int)); 93 | break; 94 | case CONFLICTING_FILE_TYPE: 95 | len = qstpncpy(buf, "ELF file with PHT can not be ET_REL", bufsize) - buf; 96 | break; 97 | case BAD_SHSTRNDX: 98 | { 99 | uint idx = va_arg(va, uint); 100 | uint num = va_arg(va, uint); 101 | len = qsnprintf(buf, bufsize, 102 | "Section header string table index %u is out of bounds", 103 | idx); 104 | if ( num > 0 ) 105 | len += qsnprintf(buf + len, bufsize - len, 106 | " (max %u)", num - 1); 107 | } 108 | break; 109 | case ERR_READ: 110 | { 111 | size_t d1 = va_arg(va, size_t); // size 112 | size_t d2 = va_arg(va, size_t); // return code 113 | qnotused(d1); 114 | qnotused(d2); 115 | len = qsnprintf(buf, bufsize, 116 | "Bad file structure or read error (offset %" FMT_64 "u)", 117 | va_arg(va, int64)); 118 | } 119 | break; 120 | default: 121 | if ( is_error(code) ) 122 | INTERR(20034); 123 | len = qsnprintf(buf, bufsize, "Unknown ELF warning %d", code); 124 | break; 125 | } 126 | return len; 127 | } 128 | 129 | //---------------------------------------------------------------------------- 130 | static bool default_error_handler(const reader_t &reader, reader_t::errcode_t code, ...) 131 | { 132 | va_list va; 133 | va_start(va, code); 134 | char buf[MAXSTR]; 135 | reader.prepare_error_string(buf, sizeof(buf), code, va); 136 | va_end(va); 137 | 138 | warning("%s", buf); 139 | return reader.is_warning(code); // resume after warnings 140 | } 141 | 142 | //---------------------------------------------------------------------------- 143 | const qstring &sym_rel::get_original_name(const reader_t &reader) const 144 | { 145 | if ( original_name.empty() ) 146 | { 147 | symrel_idx_t sym_idx = reader.symbols.get_idx(this); 148 | reader.get_name(&original_name, sym_idx.type, original.st_name); 149 | } 150 | 151 | return original_name; 152 | } 153 | 154 | //---------------------------------------------------------------------------- 155 | ea_t sym_rel::get_ea(const reader_t &reader, ea_t _debug_segbase) const 156 | { 157 | ea_t ea = value; 158 | if ( reader.is_valid_rel_file() ) 159 | { 160 | const elf_shdr_t *sh = reader.sections.getn(sec); 161 | if ( sh != NULL ) 162 | ea += sh->sh_addr; 163 | } 164 | else 165 | { 166 | ea += _debug_segbase; 167 | } 168 | return ea; 169 | } 170 | 171 | //---------------------------------------------------------------------------- 172 | void sym_rel::set_section_index(const reader_t &reader) 173 | { 174 | sec = 0; 175 | if ( original.st_shndx == SHN_XINDEX ) 176 | { 177 | symrel_idx_t sym_idx = reader.symbols.get_idx(this); 178 | const elf_shdr_t *sh_shndx; 179 | switch ( sym_idx.type ) 180 | { 181 | case SLT_SYMTAB: 182 | sh_shndx = reader.sections.get_wks(WKS_SYMTAB_SHNDX); 183 | break; 184 | case SLT_DYNSYM: 185 | sh_shndx = reader.sections.get_wks(WKS_DYNSYM_SHNDX); 186 | break; 187 | default: 188 | INTERR(20088); 189 | } 190 | // doc: "The section is an array of Elf32_Word values." 191 | uint64 offset = sym_idx.idx * sizeof(uint32); 192 | if ( sh_shndx != NULL 193 | && sh_shndx->sh_offset != 0 194 | && offset < sh_shndx->sh_size ) 195 | { 196 | sec = reader.get_shndx_at(sh_shndx->sh_offset + offset); 197 | } 198 | if ( sec == 0 ) 199 | { 200 | warning("AUTOHIDE SESSION\n" 201 | "Illegal section indirect index for symbol %u", 202 | sym_idx.idx); 203 | } 204 | } 205 | else if ( original.st_shndx < SHN_LORESERVE ) 206 | { 207 | sec = original.st_shndx; 208 | } 209 | } 210 | 211 | //---------------------------------------------------------------------------- 212 | reader_t::reader_t(linput_t *_li, int64 _start_in_file) 213 | : pheaders(this), 214 | sections(this), 215 | sym_strtab(), 216 | dyn_strtab(), 217 | li(_li), 218 | sif(_start_in_file), 219 | mappings(), 220 | arch_specific(NULL), 221 | load_bias(0), 222 | eff_msb(false), 223 | eff_64(false), 224 | seg_64(false) 225 | { 226 | set_handler(default_error_handler); 227 | filesize = qlsize(li); 228 | } 229 | 230 | //---------------------------------------------------------------------------- 231 | bool reader_t::is_warning(errcode_t code) const 232 | { 233 | return code <= LAST_WARNING; 234 | } 235 | 236 | //---------------------------------------------------------------------------- 237 | bool reader_t::is_error(errcode_t code) const 238 | { 239 | QASSERT(20035, code <= LAST_ERROR); 240 | return code > LAST_WARNING; 241 | } 242 | 243 | //------------------------------------------------------------------------- 244 | static bool _silent_handler(const reader_t &reader, reader_t::errcode_t code, ...) 245 | { 246 | return reader.is_warning(code); // resume after warnings 247 | } 248 | 249 | //---------------------------------------------------------------------------- 250 | void reader_t::set_handler(bool (*_handler)(const reader_t &reader, errcode_t code, ...)) 251 | { 252 | handle_error = _handler == NULL ? _silent_handler : _handler; 253 | } 254 | 255 | bool reader_t::read_ident() 256 | { 257 | input_status_t save_excursion(*this); 258 | if ( save_excursion.seek(0) == -1 ) 259 | return false; 260 | 261 | uint64 fsize = size(); 262 | uint64 fpos = tell(); 263 | if ( fpos >= fsize ) 264 | return false; 265 | uint64 bytes_left = fsize - fpos; 266 | if ( bytes_left < sizeof(elf_ident_t) ) 267 | return false; 268 | 269 | memset(&header, 0, sizeof(header)); 270 | 271 | if ( qlread(li, &header.e_ident, sizeof(elf_ident_t)) != sizeof(elf_ident_t) ) 272 | return false; 273 | 274 | if ( !header.e_ident.is_valid() ) 275 | return false; 276 | 277 | size_t ehdr_sz = is_64() ? sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr); 278 | if ( bytes_left < ehdr_sz ) 279 | return false; 280 | 281 | return true; 282 | } 283 | 284 | //---------------------------------------------------------------------------- 285 | int reader_t::safe_read(void *buf, size_t sz, bool apply_endianness) const 286 | { 287 | int rc = lreadbytes(li, buf, sz, apply_endianness ? is_msb() : false); 288 | if ( rc < 0 ) 289 | handle_error(*this, ERR_READ, sz, size_t(rc), qltell(li)); 290 | return rc; 291 | } 292 | 293 | //---------------------------------------------------------------------------- 294 | int reader_t::read_addr(void *buf) const 295 | { 296 | return safe_read(buf, stdsizes.types.elf_addr); 297 | } 298 | 299 | //---------------------------------------------------------------------------- 300 | int reader_t::read_off(void *buf) const 301 | { 302 | return safe_read(buf, stdsizes.types.elf_off); 303 | } 304 | 305 | //---------------------------------------------------------------------------- 306 | int reader_t::read_xword(void *buf) const 307 | { 308 | return safe_read(buf, stdsizes.types.elf_xword); 309 | } 310 | 311 | //---------------------------------------------------------------------------- 312 | int reader_t::read_sxword(void *buf) const 313 | { 314 | return safe_read(buf, stdsizes.types.elf_sxword); 315 | } 316 | 317 | //---------------------------------------------------------------------------- 318 | int reader_t::read_word(uint32 *buf) const 319 | { 320 | return safe_read(buf, 4); 321 | } 322 | 323 | //---------------------------------------------------------------------------- 324 | int reader_t::read_half(uint16 *buf) const 325 | { 326 | return safe_read(buf, 2); 327 | } 328 | 329 | //---------------------------------------------------------------------------- 330 | int reader_t::read_byte(uint8 *buf) const 331 | { 332 | return safe_read(buf, 1); 333 | } 334 | 335 | //------------------------------------------------------------------------- 336 | int reader_t::read_symbol(elf_sym_t *buf) const 337 | { 338 | #define _safe(expr) if ( (expr) < 0 ) goto FAILED_RS 339 | if ( is_64() ) 340 | { 341 | _safe(read_word(&buf->st_name)); 342 | _safe(read_byte(&buf->st_info)); 343 | _safe(read_byte(&buf->st_other)); 344 | _safe(read_half(&buf->st_shndx)); 345 | _safe(read_addr(&buf->st_value)); 346 | _safe(read_xword(&buf->st_size)); 347 | } 348 | else 349 | { 350 | _safe(read_word(&buf->st_name)); 351 | _safe(read_addr(&buf->st_value)); 352 | _safe(read_word((uint32 *) &buf->st_size)); 353 | _safe(read_byte(&buf->st_info)); 354 | _safe(read_byte(&buf->st_other)); 355 | _safe(read_half(&buf->st_shndx)); 356 | } 357 | return 0; 358 | FAILED_RS: 359 | return -1; 360 | #undef _safe 361 | } 362 | 363 | #define IS_EXEC_OR_DYN(x) ((x) == ET_EXEC || (x) == ET_DYN) 364 | 365 | struct linuxcpu_t 366 | { 367 | uint16 machine; 368 | bool msb; 369 | bool _64; 370 | }; 371 | 372 | static const linuxcpu_t lincpus[] = 373 | { 374 | { EM_386, false, false }, 375 | { EM_486, false, false }, 376 | { EM_X86_64, false, true }, 377 | }; 378 | 379 | //---------------------------------------------------------------------------- 380 | // Linux kernel loader ignores class and endian fields for some(?) processors. 381 | // check for such situation and set the effective endiannes/bitness 382 | bool reader_t::check_ident() 383 | { 384 | for ( unsigned i = 0; i < qnumber(lincpus); i++ ) 385 | { 386 | bool matched = false; 387 | bool swap; 388 | if ( eff_msb == lincpus[i].msb 389 | && header.e_machine == lincpus[i].machine 390 | && IS_EXEC_OR_DYN(header.e_type) ) 391 | { 392 | matched = true; 393 | swap = false; 394 | } 395 | else if ( eff_msb != lincpus[i].msb 396 | && swap16(header.e_machine) == lincpus[i].machine 397 | && IS_EXEC_OR_DYN(swap16(header.e_type)) ) 398 | { 399 | matched = true; 400 | swap = true; 401 | } 402 | if ( matched ) 403 | { 404 | if ( swap ) 405 | { 406 | header.e_machine = swap16(header.e_machine); 407 | header.e_type = swap16(header.e_type); 408 | if ( !handle_error(*this, BAD_ENDIANNESS, header.e_ident.bytesex) ) 409 | return false; 410 | eff_msb = lincpus[i].msb; 411 | } 412 | // segment bitness can be different from elf bitness: apparently there 413 | // are some files like that in the wild (see pc_odd_bitness_64.elf) 414 | seg_64 = lincpus[i]._64; 415 | // assume elf32 for EM_386/EM_486 416 | if ( !seg_64 ) 417 | eff_64 = false; 418 | break; 419 | } 420 | } 421 | return true; 422 | } 423 | 424 | //---------------------------------------------------------------------------- 425 | bool reader_t::read_header() 426 | { 427 | // 32/64 428 | uint8 elf_class = get_ident().elf_class; 429 | if ( elf_class != ELFCLASS32 430 | && elf_class != ELFCLASS64 ) 431 | { 432 | if ( !handle_error(*this, BAD_CLASS, elf_class) ) 433 | return false; 434 | } 435 | // lsb/msb 436 | uint8 elf_do = get_ident().bytesex; 437 | if ( elf_do != ELFDATA2LSB 438 | && elf_do != ELFDATA2MSB ) 439 | { 440 | if ( !handle_error(*this, BAD_ENDIANNESS, elf_do) ) 441 | return false; 442 | } 443 | 444 | input_status_t save_excursion(*this); 445 | if ( save_excursion.seek(sizeof(elf_ident_t)) == -1 ) 446 | return false; 447 | 448 | // set the default values from ident 449 | eff_msb = elf_do == ELFDATA2MSB; 450 | eff_64 = elf_class == ELFCLASS64; 451 | seg_64 = eff_64; 452 | 453 | // Read the type and machine 454 | #define _safe(expr) if ( (expr) < 0 ) goto FAILED 455 | _safe(read_half(&header.e_type)); 456 | _safe(read_half(&header.e_machine)); 457 | 458 | if ( !check_ident() ) 459 | return false; 460 | 461 | // Define sizes 462 | if ( !is_64() ) 463 | { 464 | stdsizes.ehdr = sizeof(Elf32_Ehdr); 465 | stdsizes.phdr = sizeof(Elf32_Phdr); 466 | stdsizes.shdr = sizeof(Elf32_Shdr); 467 | stdsizes.entries.sym = sizeof(Elf32_Sym); 468 | stdsizes.entries.dyn = sizeof(Elf32_Dyn); 469 | stdsizes.entries.rel = sizeof(Elf32_Rel); 470 | stdsizes.entries.rela = sizeof(Elf32_Rela); 471 | stdsizes.types.elf_addr = 4; 472 | stdsizes.types.elf_off = 4; 473 | stdsizes.types.elf_xword= 4; 474 | stdsizes.types.elf_sxword=4; 475 | } 476 | else 477 | { 478 | stdsizes.ehdr = sizeof(Elf64_Ehdr); 479 | stdsizes.phdr = sizeof(Elf64_Phdr); 480 | stdsizes.shdr = sizeof(Elf64_Shdr); 481 | stdsizes.entries.sym = sizeof(Elf64_Sym); 482 | stdsizes.entries.dyn = sizeof(Elf64_Dyn); 483 | stdsizes.entries.rel = sizeof(Elf64_Rel); 484 | stdsizes.entries.rela = sizeof(Elf64_Rela); 485 | stdsizes.types.elf_addr = 8; 486 | stdsizes.types.elf_off = 8; 487 | stdsizes.types.elf_xword= 8; 488 | stdsizes.types.elf_sxword=8; 489 | } 490 | stdsizes.dyn.sym = stdsizes.entries.sym; 491 | stdsizes.dyn.rel = stdsizes.entries.rel; 492 | stdsizes.dyn.rela = stdsizes.entries.rela; 493 | 494 | // Read the rest of the header 495 | _safe(read_word(&header.e_version)); 496 | _safe(read_addr(&header.e_entry)); 497 | _safe(read_off (&header.e_phoff)); 498 | _safe(read_off (&header.e_shoff)); 499 | _safe(read_word(&header.e_flags)); 500 | _safe(read_half(&header.e_ehsize)); 501 | _safe(read_half(&header.e_phentsize)); 502 | _safe(read_half(&header.e_phnum)); 503 | _safe(read_half(&header.e_shentsize)); 504 | _safe(read_half(&header.e_shnum)); 505 | _safe(read_half(&header.e_shstrndx)); 506 | #undef _safe 507 | 508 | if ( header.e_ehsize != stdsizes.ehdr ) 509 | if ( !handle_error(*this, BAD_EHSIZE, header.e_ehsize, stdsizes.ehdr) ) 510 | { 511 | FAILED: 512 | return false; 513 | } 514 | 515 | // Sanitize PHT parameters 516 | if ( (header.e_phnum == 0) != (header.e_phoff == 0) ) 517 | { 518 | if ( !handle_error(*this, BAD_PHLOC, header.e_phnum, header.e_phoff) ) 519 | goto FAILED; 520 | header.set_no_pht(); 521 | } 522 | if ( header.has_pht() && header.e_phentsize != stdsizes.phdr ) 523 | { 524 | if ( !handle_error(*this, BAD_PHENTSIZE, header.e_phentsize, stdsizes.phdr) 525 | || header.e_phentsize < stdsizes.phdr ) 526 | { 527 | goto FAILED; 528 | } 529 | header.e_phentsize = stdsizes.phdr; 530 | } 531 | 532 | // process large number of sections 533 | // "System V Application Binary Interface - DRAFT - 19 October 2010" 534 | // If the number of sections is greater than or equal to SHN_LORESERVE 535 | // (0xff00), this member has the value zero and the actual number of 536 | // section header table entries is contained in the sh_size field of the 537 | // section header at index 0. (Otherwise, the sh_size member of the 538 | // initial entry contains 0.) 539 | elf_shdr_t sh0; 540 | bool is_sh0_read; 541 | if ( header.e_shnum == 0 542 | && header.e_shoff != 0 543 | && seek(header.e_shoff) != -1 544 | && read_section_header(&sh0) 545 | && sh0.sh_type == SHT_NULL ) 546 | { 547 | is_sh0_read = true; 548 | header.real_shnum = sh0.sh_size; 549 | } 550 | else 551 | { 552 | is_sh0_read = false; 553 | header.real_shnum = header.e_shnum; 554 | } 555 | 556 | // Sanitize SHT parameters 557 | if ( (header.real_shnum == 0) != (header.e_shoff == 0) ) 558 | { 559 | if ( !handle_error(*this, BAD_SHLOC, header.real_shnum, header.e_shoff, size()) ) 560 | goto FAILED; 561 | header.set_no_sht(); // do not use sht 562 | } 563 | if ( header.has_sht() && header.e_shentsize != stdsizes.shdr ) 564 | { 565 | if ( !handle_error(*this, BAD_SHENTSIZE, header.e_shentsize, stdsizes.shdr) 566 | || header.e_shentsize < stdsizes.shdr ) 567 | { 568 | header.set_no_sht(); // do not use sht 569 | } 570 | } 571 | { 572 | uint64 sections_start = header.e_shoff; 573 | uint64 sections_finish = header.e_shoff + uint64(header.real_shnum) * header.e_shentsize; 574 | if ( sections_start > sections_finish || sections_finish > size() ) 575 | { 576 | if ( !handle_error(*this, BAD_SHLOC, header.real_shnum, header.e_shoff, size()) ) 577 | goto FAILED; 578 | header.set_no_sht(); // do not use sht 579 | } 580 | } 581 | 582 | // process large section name string table section index 583 | // "System V Application Binary Interface - DRAFT - 19 October 2010" 584 | // If the section name string table section index is greater than or equal 585 | // to SHN_LORESERVE (0xff00), this member has the value SHN_XINDEX 586 | // (0xffff) and the actual index of the section name string table section 587 | // is contained in the sh_link field of the section header at index 0. 588 | // (Otherwise, the sh_link member of the initial entry contains 0.) 589 | if ( header.e_shstrndx == SHN_XINDEX && is_sh0_read && sh0.sh_link != 0 ) 590 | header.real_shstrndx = sh0.sh_link; 591 | else 592 | header.real_shstrndx = header.e_shstrndx; 593 | 594 | // Sanitize SHT string table index 595 | if ( header.real_shstrndx > 0 596 | && header.real_shstrndx >= header.real_shnum ) 597 | { 598 | if ( !handle_error(*this, BAD_SHSTRNDX, uint(header.real_shstrndx), uint(header.real_shnum)) ) 599 | goto FAILED; 600 | header.real_shstrndx = 0; 601 | } 602 | 603 | // 604 | if ( header.has_pht() && header.e_type == ET_REL ) 605 | { 606 | if ( !handle_error(*this, CONFLICTING_FILE_TYPE) ) 607 | goto FAILED; 608 | } 609 | 610 | // 611 | switch ( header.e_machine ) 612 | { 613 | case EM_ARM: 614 | case EM_AARCH64: 615 | delete arch_specific; 616 | arch_specific = new arm_arch_specific_t(); 617 | break; 618 | default: 619 | arch_specific = new arch_specific_t(); // Dummy 620 | break; 621 | } 622 | return true; 623 | } 624 | 625 | //---------------------------------------------------------------------------- 626 | bool reader_t::read_section_header(elf_shdr_t *sh) 627 | { 628 | #define _safe(expr) if ( expr < 0 ) return false; 629 | _safe(read_word (&sh->sh_name)); 630 | _safe(read_word (&sh->sh_type)); 631 | _safe(read_xword(&sh->sh_flags)); 632 | _safe(read_addr (&sh->sh_addr)); 633 | _safe(read_off (&sh->sh_offset)); 634 | _safe(read_xword(&sh->sh_size)); 635 | _safe(read_word (&sh->sh_link)); 636 | _safe(read_word (&sh->sh_info)); 637 | _safe(read_xword(&sh->sh_addralign)); 638 | _safe(read_xword(&sh->sh_entsize)); 639 | #undef _safe 640 | return true; 641 | } 642 | 643 | //------------------------------------------------------------------------- 644 | bool reader_t::read_compression_header(elf_chdr_t *out) 645 | { 646 | #define _safe(expr) if ( expr < 0 ) return false; 647 | _safe(read_word(&out->ch_type)); 648 | if ( is_64() ) 649 | _safe(read_word(&out->ch_reserved)); 650 | _safe(read_xword(&out->ch_size)); 651 | _safe(read_xword(&out->ch_addralign)); 652 | #undef _safe 653 | return true; 654 | } 655 | 656 | //---------------------------------------------------------------------------- 657 | bool reader_t::read_section_headers() 658 | { 659 | if ( !header.has_sht() ) 660 | return false; 661 | input_status_t save_excursion(*this); 662 | if ( save_excursion.seek(header.e_shoff) == -1 ) 663 | return false; 664 | 665 | sections.resize(header.real_shnum); 666 | 667 | sections.initialized = true; 668 | 669 | for ( elf_shndx_t i = 0; i < header.real_shnum; i++ ) 670 | { 671 | if ( !seek_to_section_header(i) ) 672 | return false; 673 | 674 | elf_shdr_t *sh = sections.getn(i); 675 | if ( !read_section_header(sh) ) 676 | return false; 677 | } 678 | 679 | // in the first pass we store WKS_SYMTAB/WKS_DYNSYM to process sections 680 | // of type SHT_SYMTAB_SHNDX in the second pass 681 | typedef elf_shdrs_t::const_iterator const_iter; 682 | const_iter it = sections.begin(); 683 | const_iter end = sections.end(); 684 | for ( elf_shndx_t i = 0; it != end; ++it, ++i ) 685 | { 686 | if ( i == 0 ) // Skip first header 687 | continue; 688 | const elf_shdr_t &sh = *it; 689 | if ( sh.sh_size == 0 ) 690 | continue; 691 | 692 | switch ( sh.sh_type ) 693 | { 694 | case SHT_SYMTAB: 695 | { 696 | sections.set_index(WKS_SYMTAB, i); 697 | elf_shdr_t *strtab_sh = sections.getn(sh.sh_link); 698 | if ( strtab_sh == NULL ) 699 | { 700 | msg("Illegal link section %d of the string table " 701 | "for symbols\n", 702 | sh.sh_link); 703 | } 704 | else 705 | { 706 | set_sh_strtab(sym_strtab, *strtab_sh, true); 707 | } 708 | } 709 | break; 710 | 711 | case SHT_DYNSYM: 712 | { 713 | sections.set_index(WKS_DYNSYM, i); 714 | elf_shdr_t *strtab_sh = sections.getn(sh.sh_link); 715 | if ( strtab_sh == NULL ) 716 | { 717 | msg("Illegal link section %d of the string table " 718 | "for dynamic linking symbols\n", 719 | sh.sh_link); 720 | } 721 | else 722 | { 723 | set_sh_strtab(dyn_strtab, *strtab_sh, true); 724 | } 725 | } 726 | break; 727 | 728 | case SHT_DYNAMIC: 729 | { 730 | elf_shdr_t *strtab_sh = sections.getn(sh.sh_link); 731 | if ( strtab_sh == NULL ) 732 | { 733 | msg("Illegal link section %d of the dynamic linking " 734 | "information section\n", 735 | sh.sh_link); 736 | } 737 | else if ( strtab_sh->sh_type == SHT_DYNSYM ) 738 | { 739 | // OAT file: .dynamic section links to .dynsym section 740 | strtab_sh->sh_link = 0; 741 | } 742 | else 743 | { 744 | set_sh_strtab(dyn_strtab, *strtab_sh, true); 745 | } 746 | } 747 | break; 748 | } 749 | } 750 | 751 | // initialize the section name string table 752 | if ( header.real_shstrndx != 0 ) 753 | { 754 | elf_shdr_t *shstrtab = sections.getn(header.real_shstrndx); 755 | if ( shstrtab != NULL ) 756 | { 757 | // we do not check type of this section here 758 | // (in some cases it may be not SHT_STRTAB) 759 | sections.strtab.offset = shstrtab->sh_offset; 760 | sections.strtab.addr = shstrtab->sh_addr; 761 | sections.strtab.size = shstrtab->sh_size; 762 | } 763 | } 764 | 765 | qstring name; 766 | it = sections.begin(); 767 | for ( elf_shndx_t i = 0; it != end; ++it, ++i ) 768 | { 769 | if ( i == 0 ) // Skip first header 770 | continue; 771 | 772 | const elf_shdr_t &sh = *it; 773 | if ( sh.sh_size == 0 ) 774 | continue; 775 | 776 | name.qclear(); 777 | sections.get_name(&name, &sh); 778 | switch ( sh.sh_type ) 779 | { 780 | case SHT_STRTAB: 781 | // we specify replace = false as this section has less priority 782 | // compared to the sh_link section 783 | if ( name == ".strtab" ) 784 | set_sh_strtab(sym_strtab, sh, false); 785 | else if ( name == ".dynstr" ) 786 | set_sh_strtab(dyn_strtab, sh, false); 787 | break; 788 | 789 | case SHT_SYMTAB_SHNDX: 790 | if ( sh.sh_link != 0 ) 791 | { 792 | if ( sh.sh_link == sections.get_index(WKS_SYMTAB) ) 793 | sections.set_index(WKS_SYMTAB_SHNDX, i); 794 | if ( sh.sh_link == sections.get_index(WKS_DYNSYM) ) 795 | sections.set_index(WKS_DYNSYM_SHNDX, i); 796 | } 797 | break; 798 | 799 | case SHT_GNU_verdef: 800 | sections.set_index(WKS_VERDEF, i); 801 | break; 802 | case SHT_GNU_verneed: 803 | sections.set_index(WKS_VERNEED, i); 804 | break; 805 | case SHT_GNU_versym: 806 | sections.set_index(WKS_VERSYM, i); 807 | break; 808 | 809 | case SHT_PROGBITS: 810 | if ( name == ".interp" ) 811 | { 812 | sections.set_index(WKS_INTERP, i); 813 | break; 814 | } 815 | else if ( name == ".got" ) 816 | { 817 | sections.set_index(WKS_GOT, i); 818 | sections.set_got_original(); 819 | break; 820 | } 821 | else if ( name == ".got.plt" ) 822 | { 823 | sections.set_index(WKS_GOTPLT, i); 824 | break; 825 | } 826 | else if ( name == ".plt.got" ) 827 | { 828 | sections.set_index(WKS_PLTGOT, i); 829 | break; 830 | } 831 | // function pointers for PPC64 (may be for IA64, HPPA64) 832 | else if ( is_64() && name == ".opd" ) 833 | { 834 | sections.set_index(WKS_OPD, i); 835 | break; 836 | } 837 | // no break 838 | case SHT_NOBITS: 839 | if ( name == ".plt" ) 840 | sections.set_index(WKS_PLT, i); 841 | break; 842 | } 843 | } 844 | 845 | if ( sections.get_index(WKS_GOTPLT) == 0 ) 846 | sections.set_index(WKS_GOTPLT, sections.get_index(WKS_GOT)); 847 | else if ( sections.get_index(WKS_GOT) == 0 ) 848 | sections.set_index(WKS_GOTPLT, 0); // unsupported format 849 | 850 | return true; 851 | } 852 | 853 | //---------------------------------------------------------------------------- 854 | bool reader_t::read_program_headers() 855 | { 856 | if ( !header.has_pht() ) 857 | return false; 858 | input_status_t save_excursion(*this); 859 | if ( save_excursion.seek(header.e_phoff) == -1 ) 860 | return false; 861 | 862 | int count = header.e_phnum; 863 | #ifdef BUILD_LOADER 864 | validate_array_count_or_die(get_linput(), count, header.e_phentsize, "PHT entries"); 865 | #endif 866 | pheaders.resize(count); 867 | 868 | pheaders.initialized = true; 869 | 870 | elf_phdr_t *dyn_phdr = NULL; 871 | for ( int i = 0; i < count; i++ ) 872 | { 873 | if ( !seek_to_program_header(i) ) 874 | return false; 875 | 876 | elf_phdr_t *phdr = pheaders.get(i); 877 | #define _safe(expr) \ 878 | do \ 879 | { \ 880 | if ( expr < 0 ) \ 881 | { \ 882 | pheaders.resize(i == 0 ? 0 : i-1); \ 883 | return false; \ 884 | } \ 885 | } while ( false ) 886 | _safe(read_word(&phdr->p_type)); 887 | if ( is_64() ) 888 | _safe(read_word(&phdr->p_flags)); 889 | _safe(read_off(&phdr->p_offset)); 890 | _safe(read_addr(&phdr->p_vaddr)); 891 | _safe(read_addr(&phdr->p_paddr)); 892 | _safe(read_xword(&phdr->p_filesz)); 893 | _safe(read_xword(&phdr->p_memsz)); 894 | if ( !is_64() ) 895 | _safe(read_word(&phdr->p_flags)); 896 | _safe(read_xword(&phdr->p_align)); 897 | #undef _safe 898 | 899 | switch ( phdr->p_type ) 900 | { 901 | case PT_LOAD: 902 | add_mapping(*phdr); 903 | 904 | // ELF_Format.pdf page 2-4 905 | // The base address in ELF is "the lowest virtual address associated 906 | // with the memory image of the program's object file". 907 | if ( phdr->p_vaddr < pheaders.get_image_base() ) 908 | pheaders.set_image_base(phdr->p_vaddr); 909 | 910 | break; 911 | case PT_DYNAMIC: 912 | dyn_phdr = phdr; 913 | break; 914 | } 915 | } 916 | 917 | if ( dyn_phdr != NULL ) 918 | { 919 | // in some files, p_filesz is 0, so take max of the two 920 | // TODO: use the size of the surrounding PT_LOAD segment, 921 | // since the dynamic loader does not use the size field 922 | size_t dsize = qmax(dyn_phdr->p_filesz, dyn_phdr->p_memsz); 923 | pheaders.set_dynlink_table_info(dyn_phdr->p_offset, dyn_phdr->p_vaddr, dsize, -1); 924 | } 925 | 926 | return true; 927 | } 928 | 929 | //---------------------------------------------------------------------------- 930 | void reader_t::set_sh_strtab( 931 | dynamic_info_t::entry_t &strtab, 932 | const elf_shdr_t &strtab_sh, 933 | bool replace) 934 | { 935 | // we don't check that type of section should be SHT_STRTAB, 936 | // we just reject illegal section type 937 | if ( strtab_sh.sh_type == SHT_NULL 938 | || strtab_sh.sh_type == SHT_REL 939 | || strtab_sh.sh_type == SHT_RELA 940 | || strtab_sh.sh_type == SHT_DYNAMIC 941 | || strtab_sh.sh_type == SHT_DYNSYM 942 | || strtab_sh.sh_type == SHT_SYMTAB ) 943 | { 944 | msg("Illegal type %s of the string table section\n", 945 | sections.sh_type_str(strtab_sh.sh_type)); 946 | return; 947 | } 948 | if ( strtab_sh.sh_offset == 0 ) 949 | { 950 | msg("Illegal offset of the string table section\n"); 951 | return; 952 | } 953 | // store the string table info 954 | if ( strtab.is_valid() ) 955 | { 956 | if ( strtab.offset == strtab_sh.sh_offset ) 957 | return; 958 | warning("AUTOHIDE SESSION\n" 959 | "More than one string table for %ssymbols, " 960 | "using one at offset %08" FMT_64 "X", 961 | &strtab == &dyn_strtab ? "dynamic linking " : "", 962 | replace ? strtab_sh.sh_offset : strtab.offset); 963 | if ( !replace ) 964 | return; 965 | } 966 | strtab.offset = strtab_sh.sh_offset; 967 | strtab.addr = strtab_sh.sh_addr; 968 | strtab.size = strtab_sh.sh_size; 969 | } 970 | 971 | //---------------------------------------------------------------------------- 972 | void reader_t::set_di_strtab( 973 | dynamic_info_t::entry_t &strtab, 974 | const dynamic_info_t::entry_t &strtab_di) 975 | { 976 | if ( !strtab_di.is_valid() ) 977 | return; 978 | if ( strtab.is_valid() ) 979 | { 980 | if ( strtab.offset == strtab_di.offset ) 981 | return; 982 | warning("The dynamic section string table " 983 | "from section header (%08" FMT_64 "X) differs " 984 | "from DT_STRTAB's one (%08" FMT_64 "X), " 985 | "using the latter", 986 | strtab.offset, 987 | strtab_di.offset); 988 | } 989 | strtab = strtab_di; 990 | } 991 | 992 | //---------------------------------------------------------------------------- 993 | bool reader_t::read_notes(notes_t *notes) 994 | { 995 | notes->clear(); 996 | 997 | if ( sections.initialized ) 998 | { 999 | for ( elf_shdrs_t::const_iterator p=sections.begin(); p != sections.end(); ++p ) 1000 | { 1001 | const elf_shdr_t &sh = *p; 1002 | if ( sh.sh_type != SHT_NOTE ) 1003 | continue; 1004 | bytevec_t buf; 1005 | sections.read_file_contents(&buf, sh); 1006 | notes->add(buf); 1007 | } 1008 | } 1009 | 1010 | if ( pheaders.initialized ) 1011 | { 1012 | for ( elf_phdrs_t::const_iterator q=pheaders.begin(); q != pheaders.end(); ++q ) 1013 | { 1014 | const elf_phdr_t &p = *q; 1015 | if ( p.p_type != PT_NOTE ) 1016 | continue; 1017 | bytevec_t buf; 1018 | pheaders.read_file_contents(&buf, p); 1019 | notes->add(buf); 1020 | } 1021 | } 1022 | 1023 | notes->initialized = true; 1024 | return true; 1025 | } 1026 | 1027 | //---------------------------------------------------------------------------- 1028 | elf_sym_idx_t reader_t::rel_info_index(const elf_rel_t &r) const 1029 | { 1030 | if ( is_64() ) 1031 | return ELF64_R_SYM(r.r_info); 1032 | else 1033 | return ELF32_R_SYM(r.r_info); 1034 | } 1035 | 1036 | //---------------------------------------------------------------------------- 1037 | uint32 reader_t::rel_info_type(const elf_rel_t &r) const 1038 | { 1039 | if ( is_64() ) 1040 | return ELF64_R_TYPE(r.r_info); 1041 | else 1042 | return ELF32_R_TYPE(r.r_info); 1043 | } 1044 | 1045 | //---------------------------------------------------------------------------- 1046 | elf_sym_idx_t reader_t::rel_info_index(const elf_rela_t &r) const 1047 | { 1048 | if ( is_64() ) 1049 | return ELF64_R_SYM(r.r_info); 1050 | else 1051 | return ELF32_R_SYM(r.r_info); 1052 | } 1053 | 1054 | //---------------------------------------------------------------------------- 1055 | uint32 reader_t::rel_info_type(const elf_rela_t &r) const 1056 | { 1057 | if ( is_64() ) 1058 | return ELF64_R_TYPE(r.r_info); 1059 | else 1060 | return ELF32_R_TYPE(r.r_info); 1061 | } 1062 | 1063 | //---------------------------------------------------------------------------- 1064 | const char *reader_t::file_type_str() const 1065 | { 1066 | const char *file_type = "Unknown"; 1067 | switch ( header.e_type ) 1068 | { 1069 | case ET_NONE: file_type = "None"; break; 1070 | case ET_REL: file_type = "Relocatable"; break; 1071 | case ET_EXEC: file_type = "Executable"; break; 1072 | case ET_DYN: file_type = "Shared object"; break; 1073 | case ET_CORE: file_type = "Core file"; break; 1074 | case ET_LOPROC: file_type = "Processor specific"; break; 1075 | case ET_HIPROC: file_type = "Processor specific"; break; 1076 | case ET_IRX: 1077 | if ( header.e_machine == EM_MIPS ) 1078 | file_type = "PS2 IRX"; 1079 | break; 1080 | case ET_PSPEXEC: 1081 | if ( header.e_machine == EM_MIPS ) 1082 | file_type = "PSP executable"; 1083 | break; 1084 | case ET_PS3PRX: 1085 | if ( header.e_machine == EM_PPC64 ) 1086 | file_type = "Sony PS3 PRX file"; 1087 | break; 1088 | case ET_SCE_EXEC: 1089 | file_type = "Sony PS4 Executable"; 1090 | break; 1091 | case ET_SCE_DYNEXEC: 1092 | file_type = "Sony PS4 Main module"; 1093 | break; 1094 | case ET_SCE_RELEXEC: 1095 | file_type = "Sony PS4 PS4 Reloacatable PRX"; 1096 | break; 1097 | case ET_SCE_STUBLIB: 1098 | file_type = "Sony PS4 Stub library"; 1099 | break; 1100 | case ET_SCE_DYNAMIC: 1101 | file_type = "Sony PS4 Dynamic PRX"; 1102 | break; 1103 | } 1104 | return file_type; 1105 | } 1106 | 1107 | //---------------------------------------------------------------------------- 1108 | const char *reader_t::os_abi_str() const 1109 | { 1110 | uint8 os_abi = get_ident().osabi; 1111 | const char *abi; 1112 | switch ( os_abi ) 1113 | { 1114 | case ELFOSABI_NONE: abi = "UNIX System V ABI"; break; 1115 | case ELFOSABI_HPUX: abi = "HP-UX operating system"; break; 1116 | case ELFOSABI_NETBSD: abi = "NetBSD"; break; 1117 | case ELFOSABI_LINUX: abi = "GNU/Linux"; break; 1118 | case ELFOSABI_HURD: abi = "GNU/Hurd"; break; 1119 | case ELFOSABI_SOLARIS: abi = "Solaris"; break; 1120 | case ELFOSABI_AIX: abi = "AIX"; break; 1121 | case ELFOSABI_IRIX: abi = "IRIX"; break; 1122 | case ELFOSABI_FREEBSD: abi = "FreeBSD"; break; 1123 | case ELFOSABI_TRU64: abi = "TRU64 UNIX"; break; 1124 | case ELFOSABI_MODESTO: abi = "Novell Modesto"; break; 1125 | case ELFOSABI_OPENBSD: abi = "OpenBSD"; break; 1126 | case ELFOSABI_OPENVMS: abi = "OpenVMS"; break; 1127 | case ELFOSABI_NSK: abi = "Hewlett-Packard Non-Stop Kernel"; break; 1128 | case ELFOSABI_AROS: abi = "Amiga Research OS"; break; 1129 | case ELFOSABI_ARM: abi = "ARM"; break; 1130 | case ELFOSABI_STANDALONE: abi = "Standalone (embedded) application"; break; 1131 | case ELFOSABI_CELLOSLV2: 1132 | if ( header.e_machine == EM_PPC64 ) 1133 | { 1134 | abi = "PS3 Cell OS lv2"; 1135 | break; 1136 | } 1137 | // fall through 1138 | default: 1139 | abi = "Unknown"; 1140 | break; 1141 | } 1142 | return abi; 1143 | } 1144 | 1145 | //---------------------------------------------------------------------------- 1146 | const char *reader_t::machine_name_str() const 1147 | { 1148 | uint32 m = get_header().e_machine; 1149 | switch ( m ) 1150 | { 1151 | case EM_NONE: return ""; 1152 | case EM_M32: return "AT & T WE 32100"; 1153 | case EM_SPARC: return "SPARC"; 1154 | case EM_386: return "Intel 386"; 1155 | case EM_68K: return "Motorola 68000"; 1156 | case EM_88K: return "Motorola 88000"; 1157 | case EM_486: return "Intel 486"; 1158 | case EM_860: return "Intel 860"; 1159 | case EM_MIPS: return "MIPS"; 1160 | case EM_S370: return "IBM System370"; 1161 | case EM_MIPS_RS3_BE: return "MIPS R3000 Big Endian"; 1162 | case EM_PARISC: return "PA-RISC"; 1163 | case EM_VPP550: return "Fujitsu VPP500"; 1164 | case EM_SPARC32PLUS: return "SPARC v8+"; 1165 | case EM_I960: return "Intel 960"; 1166 | case EM_PPC: return "PowerPC"; 1167 | case EM_PPC64: return "PowerPC 64"; 1168 | case EM_S390: return "IBM S/390"; 1169 | case EM_SPU: return "Cell BE SPU"; 1170 | case EM_CISCO7200: return "Cisco 7200 Series Router (MIPS)"; 1171 | case EM_CISCO3620: return "Cisco 3620/3640 Router (MIPS)"; 1172 | case EM_V800: return "NEC V800"; 1173 | case EM_FR20: return "Fujitsu FR20"; 1174 | case EM_RH32: return "TRW RH-22"; 1175 | case EM_MCORE: return "Motorola M*Core"; 1176 | case EM_ARM: return "ARM"; 1177 | case EM_OLD_ALPHA: return "Digital Alpha"; 1178 | case EM_SH: return "SuperH"; 1179 | case EM_SPARC64: return "SPARC 64"; 1180 | case EM_TRICORE: return "Siemens Tricore"; 1181 | case EM_ARC: return "ARC"; 1182 | case EM_H8300: return "H8/300"; 1183 | case EM_H8300H: return "H8/300H"; 1184 | case EM_H8S: return "Hitachi H8S"; 1185 | case EM_H8500: return "H8/500"; 1186 | case EM_IA64: return "Itanium IA64"; 1187 | case EM_MIPS_X: return "Stanford MIPS-X"; 1188 | case EM_COLDFIRE: return "Coldfire"; 1189 | case EM_6812: return "MC68HC12"; 1190 | case EM_MMA: return "Fujitsu MMA"; 1191 | case EM_PCP: return "Siemens PCP"; 1192 | case EM_NCPU: return "Sony nCPU"; 1193 | case EM_NDR1: return "Denso NDR1"; 1194 | case EM_STARCORE: return "Star*Core"; 1195 | case EM_ME16: return "Toyota ME16"; 1196 | case EM_ST100: return "ST100"; 1197 | case EM_TINYJ: return "TinyJ"; 1198 | case EM_X86_64: return "x86-64"; 1199 | case EM_PDSP: return "PDSP"; 1200 | case EM_PDP10: return "DEC PDP-10"; 1201 | case EM_PDP11: return "DEC PDP-11"; 1202 | case EM_FX66: return "Siemens FX66"; 1203 | case EM_ST9: return "ST9+"; 1204 | case EM_ST7: return "ST7"; 1205 | case EM_68HC16: return "MC68HC16"; 1206 | case EM_6811: return "MC68HC11"; 1207 | case EM_68HC08: return "MC68HC08"; 1208 | case EM_68HC05: return "MC68HC05"; 1209 | case EM_SVX: return "Silicon Graphics SVx"; 1210 | case EM_ST19: return "ST19"; 1211 | case EM_VAX: return "VAX"; 1212 | case EM_CRIS: return "CRIS"; 1213 | case EM_JAVELIN: return "Infineon Javelin"; 1214 | case EM_FIREPATH: return "Element 14 Firepath"; 1215 | case EM_ZSP: return "ZSP"; 1216 | case EM_MMIX: return "MMIX"; 1217 | case EM_HUANY: return "Harvard HUANY"; 1218 | case EM_PRISM: return "SiTera Prism"; 1219 | case EM_AVR: return "Atmel"; 1220 | case EM_FR: return "Fujitsu FR"; 1221 | case EM_D10V: return "Mitsubishi D10V"; 1222 | case EM_D30V: return "Mitsubishi D30V"; 1223 | case EM_V850: // (GNU compiler) 1224 | case EM_NECV850: // (NEC compilers) 1225 | return "NEC V850"; 1226 | case EM_NECV850E1: return "NEC v850 ES/E1"; 1227 | case EM_NECV850E2: return "NEC v850 E2"; 1228 | case EM_NECV850Ex: return "NEC v850 ???"; 1229 | case EM_M32R: return "M32R"; 1230 | case EM_MN10300: return "MN10300"; 1231 | case EM_MN10200: return "MN10200"; 1232 | case EM_PJ: return "picoJava"; 1233 | case EM_OPENRISC : return "OpenRISC"; 1234 | case EM_ARCOMPACT: return "ARCompact"; 1235 | case EM_XTENSA: return "Xtensa"; 1236 | case EM_VIDEOCORE: return "VideoCore"; 1237 | case EM_TMM_GPP: return "Thompson GPP"; 1238 | case EM_NS32K: return "NS 32000"; 1239 | case EM_TPC: return "TPC"; 1240 | case EM_SNP1K: return "SNP 1000"; 1241 | case EM_ST200: return "ST200"; 1242 | case EM_IP2K: return "IP2022"; 1243 | case EM_MAX: return "MAX"; 1244 | case EM_CR: return "CompactRISC"; 1245 | case EM_F2MC16: return "F2MC16"; 1246 | case EM_MSP430: return "MSP430"; 1247 | case EM_BLACKFIN: return "ADI Blackfin"; 1248 | case EM_SE_C33: return "S1C33"; 1249 | case EM_SEP: return "SEP"; 1250 | case EM_ARCA: return "Arca"; 1251 | case EM_UNICORE: return "Unicore"; 1252 | case EM_EXCESS: return "eXcess"; 1253 | case EM_DXP: return "Icera DXP"; 1254 | case EM_ALTERA_NIOS2: return "Nios II"; 1255 | case EM_CRX: return "CRX"; 1256 | case EM_XGATE: return "XGATE"; 1257 | case EM_C166: return "C16x/XC16x/ST10"; 1258 | case EM_M16C: return "M16C"; 1259 | case EM_DSPIC30F: return "dsPIC30F"; 1260 | case EM_CE: return "Freescale Communication Engine"; 1261 | case EM_M32C: return "M32C"; 1262 | case EM_TSK3000: return "TSK3000"; 1263 | case EM_RS08: return "RS08"; 1264 | case EM_ECOG2: return "eCOG2"; 1265 | case EM_SCORE: return "Sunplus Score"; 1266 | case EM_DSP24: return "NJR DSP24"; 1267 | case EM_VIDEOCORE3: return "VideoCore III"; 1268 | case EM_LATTICEMICO32: return "Lattice Mico32"; 1269 | case EM_SE_C17: return "C17"; 1270 | case EM_MMDSP_PLUS: return "MMDSP"; 1271 | case EM_CYPRESS_M8C: return "M8C"; 1272 | case EM_R32C: return "R32C"; 1273 | case EM_TRIMEDIA: return "TriMedia"; 1274 | case EM_QDSP6: return "QDSP6"; 1275 | case EM_8051: return "i8051"; 1276 | case EM_STXP7X: return "STxP7x"; 1277 | case EM_NDS32: return "NDS32"; 1278 | case EM_ECOG1X: return "eCOG1X"; 1279 | case EM_MAXQ30: return "MAXQ30"; 1280 | case EM_XIMO16: return "NJR XIMO16"; 1281 | case EM_MANIK: return "M2000"; 1282 | case EM_CRAYNV2: return "Cray NV2"; 1283 | case EM_RX: return "RX"; 1284 | case EM_METAG: return "Imagination Technologies META"; 1285 | case EM_MCST_ELBRUS: return "MCST Elbrus"; 1286 | case EM_ECOG16: return "eCOG16"; 1287 | case EM_CR16: return "CompactRISC 16-bit"; 1288 | case EM_ETPU: return "Freescale ETPU"; 1289 | case EM_SLE9X: return "SLE9X"; 1290 | case EM_L1OM: return "Intel L1OM"; 1291 | case EM_K1OM: return "Intel K1OM"; 1292 | case EM_INTEL182: return "Intel Reserved (182)"; 1293 | case EM_AARCH64: return "ARM64"; 1294 | case EM_ARM184: return "ARM Reserved (184)"; 1295 | case EM_AVR32: return "AVR32"; 1296 | case EM_STM8: return "STM8"; 1297 | case EM_TILE64: return "Tilera TILE64"; 1298 | case EM_TILEPRO: return "Tilera TILEPro"; 1299 | case EM_MICROBLAZE: return "MicroBlaze"; 1300 | case EM_CUDA: return "CUDA"; 1301 | case EM_TILEGX: return "Tilera TILE-Gx"; 1302 | case EM_CLOUDSHIELD: return "CloudShield"; 1303 | case EM_COREA_1ST: return "Core-A 1st gen"; 1304 | case EM_COREA_2ND: return "Core-A 2nd gen"; 1305 | case EM_ARC_COMPACT2: return "ARCompactV2"; 1306 | case EM_OPEN8: return "Open8"; 1307 | case EM_RL78: return "RL78"; 1308 | case EM_VIDEOCORE5: return "VideoCore V"; 1309 | case EM_78K0R: return "78K0R"; 1310 | case EM_56800EX: return "Freescale 56800EX"; 1311 | case EM_BA1: return "Beyond BA1"; 1312 | case EM_BA2: return "Beyond BA2"; 1313 | case EM_XCORE: return "XMOS xCORE"; 1314 | case EM_CYGNUS_POWERPC: return "PowerPC"; 1315 | case EM_ALPHA: return "DEC Alpha"; 1316 | case EM_TI_C6000: return "TMS320C6"; 1317 | default: 1318 | { 1319 | static char buf[30]; 1320 | qsnprintf(buf, sizeof(buf), "Unknown CPU [%u]", m); 1321 | return buf; 1322 | } 1323 | } 1324 | } 1325 | 1326 | //---------------------------------------------------------------------------- 1327 | bool reader_t::read_prelink_base(uint32 *base) 1328 | { 1329 | int64 fsize = size(); 1330 | input_status_t save_excursion(*this); 1331 | if ( save_excursion.seek(fsize - 4) == -1 ) 1332 | return false; 1333 | 1334 | char tag[4]; 1335 | bool ok = false; 1336 | if ( qlread(li, tag, 4) == 4 ) 1337 | { 1338 | if ( memcmp(tag, "PRE ", 4) == 0 ) 1339 | { 1340 | if ( qlseek(li, fsize - 8) != -1 && read_word(base) >= 0 ) 1341 | ok = true; 1342 | } 1343 | } 1344 | 1345 | return ok; 1346 | } 1347 | 1348 | //---------------------------------------------------------------------------- 1349 | bool reader_t::get_string_at(qstring *out, uint64 offset) const 1350 | { 1351 | input_status_t save_excursion(*this); 1352 | if ( save_excursion.seek(offset) == -1 ) 1353 | { 1354 | out->sprnt("bad offset %08x", low(offset)); 1355 | return false; 1356 | } 1357 | 1358 | bool ret = true; 1359 | out->clear(); 1360 | char buffer[100]; 1361 | while ( true ) 1362 | { 1363 | int read = qlread(li, buffer, sizeof(buffer)); 1364 | if ( read < 0 ) 1365 | { 1366 | out->append("{truncated name}"); 1367 | ret = false; 1368 | break; 1369 | } 1370 | 1371 | // Find the position of the trailing zero 1372 | int pos; 1373 | for ( pos = 0; pos < read && buffer[pos] != '\0'; pos++ ) 1374 | ; 1375 | 1376 | out->append(buffer, pos); 1377 | if ( pos < sizeof(buffer) ) 1378 | break; 1379 | } 1380 | return ret; 1381 | } 1382 | 1383 | //---------------------------------------------------------------------------- 1384 | elf_shndx_t reader_t::get_shndx_at(uint64 offset) const 1385 | { 1386 | input_status_t save_excursion(*this); 1387 | if ( save_excursion.seek(offset) == -1 ) 1388 | return 0; 1389 | CASSERT(sizeof(elf_shndx_t) == sizeof(uint32)); 1390 | uint32 res; 1391 | if ( read_word(&res) < 0 ) 1392 | return 0; 1393 | return res; 1394 | } 1395 | 1396 | //-------------------------------------------------------------------------- 1397 | // Fills 'out' with either a fake entry from the DHT or an entry from the SHT. 1398 | static bool get_versym_section( 1399 | elf_shdr_t *out, 1400 | slice_type_t *slice_type, 1401 | const reader_t &reader, 1402 | wks_t sht_idx, 1403 | const dynamic_info_t &di, 1404 | dynamic_info_type_t dht_idx, 1405 | bool use_pht) 1406 | { 1407 | *slice_type = SLT_INVALID; 1408 | if ( use_pht ) 1409 | { 1410 | if ( di.fill_section_header(out, dht_idx) ) 1411 | *slice_type = SLT_DYNSYM; 1412 | } 1413 | else 1414 | { 1415 | const elf_shdr_t *sht_entry = reader.sections.get_wks(sht_idx); 1416 | if ( sht_entry != NULL ) 1417 | { 1418 | *out = *sht_entry; 1419 | if ( sht_entry->sh_link == reader.sections.get_index(WKS_SYMTAB) 1420 | && reader.symbols.slice_size(SLT_SYMTAB) != 0 ) 1421 | { 1422 | *slice_type = SLT_SYMTAB; 1423 | } 1424 | else if ( sht_entry->sh_link == reader.sections.get_index(WKS_DYNSYM) 1425 | && reader.symbols.slice_size(SLT_DYNSYM) != 0 ) 1426 | { 1427 | *slice_type = SLT_DYNSYM; 1428 | } 1429 | } 1430 | } 1431 | return *slice_type != SLT_INVALID; 1432 | } 1433 | 1434 | //---------------------------------------------------------------------------- 1435 | // Helper class for reading version info sections. DT_VERDEF and DT_VERNEED 1436 | // have similar structures for reading main and auxiliary entries. 1437 | template 1438 | struct elf_ver_parser_t 1439 | { 1440 | const reader_t &reader; 1441 | 1442 | elf_ver_parser_t(const reader_t &_reader) 1443 | : reader(_reader) 1444 | {} 1445 | 1446 | virtual void entry_cb(const T_entry &, int64, size_t) = 0; 1447 | virtual void aux_cb(const T_aux &, int64, size_t) = 0; 1448 | 1449 | void parse(int64 offset, size_t size) 1450 | { 1451 | int64 orig_offset = offset; 1452 | input_status_t save_excursion(reader); 1453 | int64 end = offset + size; 1454 | size_t entry_idx = 0; 1455 | std::set entry_seen; 1456 | while ( offset < end && entry_seen.insert(offset).second ) 1457 | { 1458 | T_entry entry; 1459 | if ( save_excursion.seek(offset) == -1 || !entry.read(reader) ) 1460 | break; 1461 | 1462 | entry_cb(entry, offset - orig_offset, entry_idx++); 1463 | 1464 | int64 aux_offset = offset + entry.aux(); 1465 | size_t aux_idx = 0; 1466 | std::set aux_seen; 1467 | while ( aux_offset < end 1468 | && aux_seen.insert(aux_offset).second 1469 | && aux_idx < entry.cnt() ) 1470 | { 1471 | T_aux aux; 1472 | if ( save_excursion.seek(aux_offset) == -1 || !aux.read(reader) ) 1473 | break; 1474 | 1475 | aux_cb(aux, aux_offset - orig_offset, aux_idx++); 1476 | 1477 | aux_offset += aux.next(); 1478 | } 1479 | 1480 | offset += entry.next(); 1481 | } 1482 | } 1483 | }; 1484 | 1485 | //---------------------------------------------------------------------------- 1486 | bool reader_t::read_symbol_versions( 1487 | elf_symbol_version_t *symver, 1488 | const dynamic_info_t &di, 1489 | bool use_pht) 1490 | { 1491 | elf_shdr_t sh; 1492 | slice_type_t st; 1493 | 1494 | // Read version requirement entries from DT_VERNEED 1495 | struct elf_verneed_parser_t 1496 | : public elf_ver_parser_t 1497 | { 1498 | typedef elf_ver_parser_t inherited; 1499 | 1500 | elf_symbol_version_t &symver; 1501 | slice_type_t st; 1502 | elf_verneed_parser_t( 1503 | const reader_t &_reader, 1504 | elf_symbol_version_t &_symver, 1505 | slice_type_t _st) 1506 | : inherited(_reader), 1507 | symver(_symver), 1508 | st(_st) 1509 | { 1510 | } 1511 | 1512 | virtual void entry_cb(const elf_verneed_t &verneed, int64 offset, size_t) 1513 | { 1514 | symbol_verneed_t &reqfile = symver.reqs.push_back(); 1515 | reqfile.offset = offset; 1516 | // TODO check verneed.vn_version 1517 | reqfile.name = symver.file_names.size(); 1518 | qstring &fname = symver.file_names.push_back(); 1519 | reader.get_name(&fname, st, verneed.vn_file); 1520 | } 1521 | 1522 | virtual void aux_cb(const elf_vernaux_t &vernaux, int64 offset, size_t) 1523 | { 1524 | symbol_verneed_t &reqfile = symver.reqs.back(); 1525 | symbol_vernaux_t &reqver = reqfile.auxs.push_back(); 1526 | reqver.offset = offset; 1527 | 1528 | reqver.name = symver.version_names.size(); 1529 | qstring &vname = symver.version_names.push_back(); 1530 | reader.get_name(&vname, st, vernaux.vna_name); 1531 | 1532 | uint16 idx = vernaux.vna_other & ~0x8000; 1533 | if ( idx != 0 ) 1534 | { 1535 | vermap_item_t &vermap_item = symver.vermap[idx]; 1536 | vermap_item.fname_idx = reqfile.name; 1537 | vermap_item.vname_idx = reqver.name; 1538 | } 1539 | } 1540 | }; 1541 | 1542 | if ( get_versym_section(&sh, &st, *this, WKS_VERNEED, di, DIT_VERNEED, use_pht) ) 1543 | { 1544 | elf_verneed_parser_t parser(*this, *symver, st); 1545 | parser.parse(sh.sh_offset, sh.sh_size); 1546 | } 1547 | 1548 | // Read version definition entries from DT_VERDEF 1549 | struct elf_verdef_parser_t 1550 | : public elf_ver_parser_t 1551 | { 1552 | typedef elf_ver_parser_t inherited; 1553 | 1554 | elf_symbol_version_t &symver; 1555 | slice_type_t st; 1556 | elf_verdef_parser_t( 1557 | const reader_t &_reader, 1558 | elf_symbol_version_t &_symver, 1559 | slice_type_t _st) 1560 | : inherited(_reader), 1561 | symver(_symver), 1562 | st(_st) 1563 | { 1564 | } 1565 | 1566 | virtual void entry_cb(const elf_verdef_t &verdef, int64 offset, size_t) 1567 | { 1568 | symbol_verdef_t &deffile = symver.defs.push_back(); 1569 | deffile.offset = offset; 1570 | // TODO check verdef.vd_version 1571 | deffile.flags = verdef.vd_flags; 1572 | deffile.ndx = verdef.vd_ndx; 1573 | } 1574 | 1575 | virtual void aux_cb(const elf_verdaux_t &verdaux, int64 offset, size_t) 1576 | { 1577 | symbol_verdef_t &deffile = symver.defs.back(); 1578 | symbol_verdaux_t &defver = deffile.auxs.push_back(); 1579 | defver.offset = offset; 1580 | 1581 | if ( (deffile.flags & VER_FLG_BASE) != 0 ) 1582 | { 1583 | symver.def_base = symver.file_names.size(); 1584 | qstring &fname = symver.file_names.push_back(); 1585 | reader.get_name(&fname, st, verdaux.vda_name); 1586 | } 1587 | 1588 | defver.name = symver.version_names.size(); 1589 | qstring &vname = symver.version_names.push_back(); 1590 | reader.get_name(&vname, st, verdaux.vda_name); 1591 | 1592 | uint16 idx = deffile.ndx; 1593 | if ( idx != 0 && deffile.auxs.size() == 1 ) 1594 | { 1595 | vermap_item_t &vermap_item = symver.vermap[idx]; 1596 | vermap_item.fname_idx = symver.def_base; 1597 | vermap_item.vname_idx = defver.name; 1598 | } 1599 | } 1600 | }; 1601 | 1602 | if ( get_versym_section(&sh, &st, *this, WKS_VERDEF, di, DIT_VERDEF, use_pht) ) 1603 | { 1604 | elf_verdef_parser_t parser(*this, *symver, st); 1605 | parser.parse(sh.sh_offset, sh.sh_size); 1606 | } 1607 | 1608 | // Read version symbol entries from DT_VERSYM 1609 | if ( get_versym_section(&sh, &st, *this, WKS_VERSYM, di, DIT_VERSYM, use_pht) ) 1610 | { 1611 | input_status_t save_excursion(*this); 1612 | if ( save_excursion.seek(sh.sh_offset) != -1 ) 1613 | for ( size_t i = 0; i < sh.sh_size / sizeof(uint16); i++ ) 1614 | if ( read_half(&symver->symbols.push_back()) < 0 ) 1615 | break; 1616 | } 1617 | 1618 | return true; 1619 | } 1620 | 1621 | //---------------------------------------------------------------------------- 1622 | bool reader_t::read_dynamic_info_tags( 1623 | dyninfo_tags_t *dyninfo_tags, 1624 | const dynamic_linking_tables_t &dlt) 1625 | { 1626 | // assert: dlt.is_valid() 1627 | if ( dlt.size == 0 ) 1628 | return false; 1629 | 1630 | // read all 'elf_dyn_t' entries 1631 | elf_dyn_t *d; 1632 | const size_t isize = stdsizes.entries.dyn; 1633 | elf_shdr_t fake_section; 1634 | fake_section.sh_type = SHT_DYNAMIC; 1635 | fake_section.sh_offset = dlt.offset; 1636 | fake_section.sh_size = dlt.size; 1637 | fake_section.sh_entsize = isize; 1638 | buffered_input_t dyn_input(*this, fake_section); 1639 | while ( dyn_input.next(d) ) 1640 | { 1641 | dyninfo_tags->push_back(*d); 1642 | if ( d->d_tag == DT_NULL ) 1643 | break; 1644 | } 1645 | return true; 1646 | } 1647 | 1648 | //---------------------------------------------------------------------------- 1649 | bool reader_t::parse_dynamic_info( 1650 | dynamic_info_t *dyninfo, 1651 | const dyninfo_tags_t &dyninfo_tags) 1652 | { 1653 | dyninfo->initialize(*this); 1654 | 1655 | sizevec_t offsets; 1656 | 1657 | // populate dyninfo structure 1658 | for ( dyninfo_tags_t::const_iterator dyn = dyninfo_tags.begin(); 1659 | dyn != dyninfo_tags.end(); 1660 | ++dyn ) 1661 | { 1662 | dynamic_info_type_t di_type; 1663 | 1664 | di_type = dyn->d_tag == DT_STRTAB ? DIT_STRTAB 1665 | : dyn->d_tag == DT_SCE_STRTAB ? DIT_STRTAB // PS4 1666 | : dyn->d_tag == DT_SYMTAB ? DIT_SYMTAB 1667 | : dyn->d_tag == DT_SCE_SYMTAB ? DIT_SYMTAB // PS4 1668 | : dyn->d_tag == DT_REL ? DIT_REL 1669 | : dyn->d_tag == DT_RELA ? DIT_RELA 1670 | : dyn->d_tag == DT_SCE_RELA ? DIT_RELA // PS4 1671 | : dyn->d_tag == DT_JMPREL ? DIT_PLT 1672 | : dyn->d_tag == DT_HASH ? DIT_HASH 1673 | : dyn->d_tag == DT_SCE_HASH ? DIT_HASH // PS4 1674 | : dyn->d_tag == DT_GNU_HASH ? DIT_GNU_HASH 1675 | : dyn->d_tag == DT_PREINIT_ARRAY ? DIT_PREINIT_ARRAY 1676 | : dyn->d_tag == DT_INIT_ARRAY ? DIT_INIT_ARRAY 1677 | : dyn->d_tag == DT_FINI_ARRAY ? DIT_FINI_ARRAY 1678 | : dyn->d_tag == DT_VERDEF ? DIT_VERDEF 1679 | : dyn->d_tag == DT_VERNEED ? DIT_VERNEED 1680 | : dyn->d_tag == DT_VERSYM ? DIT_VERSYM 1681 | : dyn->d_tag == DT_SCE_JMPREL ? DIT_JMPREL 1682 | : DIT_TYPE_COUNT; 1683 | if ( di_type != DIT_TYPE_COUNT ) 1684 | { 1685 | dynamic_info_t::entry_t &entry = dyninfo->entries[di_type]; 1686 | entry.offset = file_offset(dyn->d_un); 1687 | offsets.push_back(entry.offset); 1688 | entry.addr = dyn->d_un; 1689 | continue; 1690 | } 1691 | 1692 | di_type = dyn->d_tag == DT_STRSZ ? DIT_STRTAB 1693 | : dyn->d_tag == DT_SCE_STRSZ ? DIT_STRTAB // PS4 1694 | : dyn->d_tag == DT_RELSZ ? DIT_REL 1695 | : dyn->d_tag == DT_RELASZ ? DIT_RELA 1696 | : dyn->d_tag == DT_SCE_RELASZ ? DIT_RELA // PS4 1697 | : dyn->d_tag == DT_PLTRELSZ ? DIT_PLT 1698 | : dyn->d_tag == DT_SCE_HASHSZ ? DIT_HASH // PS4 1699 | : dyn->d_tag == DT_PREINIT_ARRAYSZ ? DIT_PREINIT_ARRAY 1700 | : dyn->d_tag == DT_INIT_ARRAYSZ ? DIT_INIT_ARRAY 1701 | : dyn->d_tag == DT_FINI_ARRAYSZ ? DIT_FINI_ARRAY 1702 | : dyn->d_tag == DT_SCE_SYMTABSZ ? DIT_SYMTAB // PS4 1703 | : dyn->d_tag == DT_SCE_PLTRELSZ ? DIT_JMPREL // PS4 1704 | : DIT_TYPE_COUNT; 1705 | if ( di_type != DIT_TYPE_COUNT ) 1706 | { 1707 | dyninfo->entries[di_type].size = dyn->d_un; 1708 | continue; 1709 | } 1710 | 1711 | di_type = dyn->d_tag == DT_SYMENT ? DIT_SYMTAB 1712 | : dyn->d_tag == DT_SCE_SYMENT ? DIT_SYMTAB // PS4 1713 | : dyn->d_tag == DT_RELENT ? DIT_REL 1714 | : dyn->d_tag == DT_RELAENT ? DIT_RELA 1715 | : dyn->d_tag == DT_SCE_RELAENT? DIT_RELA // PS4 1716 | : DIT_TYPE_COUNT; 1717 | if ( di_type != DIT_TYPE_COUNT ) 1718 | { 1719 | dyninfo->entries[di_type].entsize = dyn->d_un; 1720 | continue; 1721 | } 1722 | 1723 | di_type = dyn->d_tag == DT_VERDEFNUM ? DIT_VERDEF 1724 | : dyn->d_tag == DT_VERNEEDNUM ? DIT_VERNEED 1725 | : DIT_TYPE_COUNT; 1726 | if ( di_type != DIT_TYPE_COUNT ) 1727 | { 1728 | dyninfo->entries[di_type].info = dyn->d_un; 1729 | continue; 1730 | } 1731 | 1732 | switch ( dyn->d_tag ) 1733 | { 1734 | case DT_PLTREL: 1735 | dyninfo->plt_rel_type = uint32(dyn->d_un); 1736 | if ( dyninfo->plt_rel_type != DT_REL && dyninfo->plt_rel_type != DT_RELA ) 1737 | { 1738 | if ( !handle_error(*this, BAD_DYN_PLT_TYPE, dyninfo->plt_rel_type) ) 1739 | return false; 1740 | } 1741 | continue; 1742 | 1743 | case DT_INIT: 1744 | case DT_FINI: 1745 | case DT_PLTGOT: 1746 | offsets.push_back(file_offset(dyn->d_un)); 1747 | continue; 1748 | 1749 | default: 1750 | msg("UNHANDELD: tag: %s \t un: %016llx\n", dyntag_to_string(dyn->d_tag).c_str(), dyn->d_un); 1751 | continue; 1752 | 1753 | case DT_NULL: 1754 | break; 1755 | } 1756 | break; 1757 | } 1758 | 1759 | // Guess size of sections that don't have an explicit size 1760 | if (dyninfo->symtab().size == 0) // PS4 1761 | dyninfo->symtab().guess_size(offsets); 1762 | dyninfo->hash().guess_size(offsets); 1763 | dyninfo->gnu_hash().guess_size(offsets); 1764 | dyninfo->verdef().guess_size(offsets); 1765 | dyninfo->verneed().guess_size(offsets); 1766 | dyninfo->versym().guess_size(offsets); 1767 | 1768 | return true; 1769 | } 1770 | 1771 | //---------------------------------------------------------------------------- 1772 | void reader_t::add_mapping(const elf_phdr_t &p) 1773 | { 1774 | mapping_t &m = mappings.push_back(); 1775 | m.offset = p.p_offset; 1776 | m.size = p.p_filesz; 1777 | m.ea = p.p_vaddr; 1778 | } 1779 | 1780 | //---------------------------------------------------------------------------- 1781 | int64 reader_t::file_offset(uint64 ea) const 1782 | { 1783 | for ( int i=0; i < mappings.size(); i++ ) 1784 | { 1785 | const mapping_t &cur = mappings[i]; 1786 | if ( cur.ea <= ea && (cur.ea + cur.size) > ea ) 1787 | return low(ea - cur.ea) + cur.offset; 1788 | } 1789 | 1790 | return -1; 1791 | } 1792 | 1793 | //---------------------------------------------------------------------------- 1794 | ea_t reader_t::file_vaddr(uint64 offset) const 1795 | { 1796 | for ( int i=0; i < mappings.size(); i++ ) 1797 | { 1798 | const mapping_t &cur = mappings[i]; 1799 | if ( cur.offset <= offset && (cur.offset + cur.size) > offset ) 1800 | return low(offset - cur.offset) + cur.ea; 1801 | } 1802 | 1803 | return BADADDR; 1804 | } 1805 | 1806 | //---------------------------------------------------------------------------- 1807 | elf_shndx_t section_headers_t::get_index(wks_t wks) const 1808 | { 1809 | QASSERT(20054, wks >= WKS_BSS && wks < WKS_LAST); 1810 | return wks_lut[int(wks)]; 1811 | } 1812 | 1813 | //---------------------------------------------------------------------------- 1814 | void section_headers_t::set_index(wks_t wks, elf_shndx_t index) 1815 | { 1816 | QASSERT(20055, wks >= WKS_BSS && wks < WKS_LAST); 1817 | wks_lut[int(wks)] = index; 1818 | } 1819 | 1820 | //---------------------------------------------------------------------------- 1821 | const elf_shdr_t *section_headers_t::getn(elf_shndx_t index) const 1822 | { 1823 | assert_initialized(); 1824 | 1825 | if ( index >= headers.size() ) 1826 | return NULL; 1827 | else 1828 | return &headers[index]; 1829 | } 1830 | 1831 | //---------------------------------------------------------------------------- 1832 | const elf_shdr_t *section_headers_t::get(uint32 sh_type, const char *name) const 1833 | { 1834 | assert_initialized(); 1835 | 1836 | qstring n2; 1837 | for ( qvector::const_iterator it=begin(); it != end(); it++ ) 1838 | { 1839 | const elf_shdr_t &cur = *it; 1840 | if ( cur.sh_type == sh_type ) 1841 | { 1842 | n2.qclear(); 1843 | get_name(&n2, &cur); 1844 | if ( n2 == name ) 1845 | return &cur; 1846 | } 1847 | } 1848 | return NULL; 1849 | } 1850 | 1851 | //---------------------------------------------------------------------------- 1852 | const elf_shdr_t *section_headers_t::get_rel_for(elf_shndx_t index, bool *is_rela) const 1853 | { 1854 | assert_initialized(); 1855 | if ( is_rela != NULL ) 1856 | *is_rela = false; 1857 | 1858 | QASSERT(20056, index > 0); 1859 | for ( elf_shdrs_t::const_iterator it=begin(); it != end(); it++ ) 1860 | { 1861 | // for REL/RELA sections, sh_info contains the index to which the relocations apply 1862 | if ( it->sh_info == index 1863 | && (it->sh_type == SHT_RELA || it->sh_type == SHT_REL) ) 1864 | { 1865 | // found it 1866 | if ( is_rela != NULL ) 1867 | *is_rela = it->sh_type == SHT_RELA; 1868 | return it; 1869 | } 1870 | } 1871 | return NULL; 1872 | } 1873 | 1874 | //---------------------------------------------------------------------------- 1875 | int section_headers_t::add(const elf_shdr_t §ion) 1876 | { 1877 | headers.push_back(section); 1878 | return headers.size() - 1; 1879 | } 1880 | 1881 | //---------------------------------------------------------------------------- 1882 | bool section_headers_t::get_name(qstring *out, elf_shndx_t index) const 1883 | { 1884 | assert_initialized(); 1885 | 1886 | if ( index >= headers.size() ) 1887 | return false; 1888 | else 1889 | return get_name(out, &headers[index]); 1890 | } 1891 | 1892 | //---------------------------------------------------------------------------- 1893 | bool section_headers_t::get_name(qstring *out, const elf_shdr_t *sh) const 1894 | { 1895 | if ( sh == NULL || !strtab.is_valid() ) 1896 | return false; 1897 | return reader->get_name(out, strtab, sh->sh_name); 1898 | } 1899 | 1900 | //---------------------------------------------------------------------------- 1901 | bool reader_t::get_name( 1902 | qstring *out, 1903 | const dynamic_info_t::entry_t &strtab, 1904 | uint32 name_idx) const 1905 | { 1906 | if ( !strtab.is_valid() ) 1907 | *out = "{no string table}"; 1908 | // cisco ios files have size 0 for the string section 1909 | else if ( strtab.size != 0 && name_idx >= strtab.size ) 1910 | out->sprnt("bad offset %08x", low(strtab.offset + name_idx)); 1911 | else 1912 | return get_string_at(out, strtab.offset + name_idx); 1913 | return false; 1914 | } 1915 | 1916 | //---------------------------------------------------------------------------- 1917 | bool reader_t::get_name( 1918 | qstring *out, 1919 | slice_type_t slice_type, 1920 | uint32 name_idx) const 1921 | { 1922 | const dynamic_info_t::entry_t *strtab; 1923 | switch ( slice_type ) 1924 | { 1925 | case SLT_SYMTAB: 1926 | strtab = &sym_strtab; 1927 | break; 1928 | case SLT_DYNSYM: 1929 | strtab = &dyn_strtab; 1930 | break; 1931 | default: 1932 | INTERR(20086); 1933 | } 1934 | return get_name(out, *strtab, name_idx); //-V614 Potentially uninitialized pointer 'strtab' used 1935 | } 1936 | 1937 | //---------------------------------------------------------------------------- 1938 | const char *section_headers_t::sh_type_str(uint32 sh_type) const 1939 | { 1940 | #define NM(tp) case SHT_##tp: return #tp 1941 | #define NM2(tp, nm) case SHT_##tp: return #nm 1942 | 1943 | // OS-specific types 1944 | uint8 os_abi = reader->get_ident().osabi; 1945 | if ( os_abi == ELFOSABI_SOLARIS ) 1946 | { 1947 | switch ( sh_type ) 1948 | { 1949 | NM(SUNW_ancillary); 1950 | NM(SUNW_capchain); 1951 | NM(SUNW_capinfo); 1952 | NM(SUNW_symsort); 1953 | NM(SUNW_tlssort); 1954 | NM(SUNW_LDYNSYM); 1955 | NM(SUNW_dof); 1956 | NM(SUNW_cap); 1957 | NM(SUNW_SIGNATURE); 1958 | NM(SUNW_ANNOTATE); 1959 | NM(SUNW_DEBUGSTR); 1960 | NM(SUNW_DEBUG); 1961 | NM(SUNW_move); 1962 | NM(SUNW_COMDAT); 1963 | NM(SUNW_syminfo); 1964 | NM2(SUNW_verdef, VERDEF); 1965 | NM2(SUNW_verneed, VERNEEDED); 1966 | NM2(SUNW_versym, VERSYMBOL); 1967 | } 1968 | } 1969 | else 1970 | { 1971 | switch ( sh_type ) 1972 | { 1973 | NM(GNU_INCREMENTAL_INPUTS); 1974 | NM(GNU_INCREMENTAL_SYMTAB); 1975 | NM(GNU_INCREMENTAL_RELOCS); 1976 | NM(GNU_INCREMENTAL_GOT_PLT); 1977 | NM(GNU_ATTRIBUTES); 1978 | NM(GNU_HASH); 1979 | NM(GNU_LIBLIST); 1980 | NM2(GNU_verdef, VERDEF); 1981 | NM2(GNU_verneed, VERNEEDED); 1982 | NM2(GNU_versym, VERSYMBOL); 1983 | } 1984 | } 1985 | 1986 | switch ( sh_type ) 1987 | { 1988 | NM(NULL); 1989 | NM(PROGBITS); 1990 | NM(SYMTAB); 1991 | NM(STRTAB); 1992 | NM(RELA); 1993 | NM(HASH); 1994 | NM(DYNAMIC); 1995 | NM(NOTE); 1996 | NM(NOBITS); 1997 | NM(REL); 1998 | NM(SHLIB); 1999 | NM(DYNSYM); 2000 | NM(INIT_ARRAY); 2001 | NM(FINI_ARRAY); 2002 | NM(PREINIT_ARRAY); 2003 | NM(GROUP); 2004 | NM(SYMTAB_SHNDX); 2005 | default: 2006 | { 2007 | uint32 m = reader->get_header().e_machine; 2008 | if ( m == EM_ARM ) 2009 | { 2010 | switch ( sh_type ) 2011 | { 2012 | NM(ARM_EXIDX); 2013 | NM(ARM_PREEMPTMAP); 2014 | NM(ARM_ATTRIBUTES); 2015 | NM(ARM_DEBUGOVERLAY); 2016 | NM(ARM_OVERLAYSECTION); 2017 | } 2018 | } 2019 | else if ( m == EM_MIPS ) 2020 | { 2021 | switch ( sh_type ) 2022 | { 2023 | NM(MIPS_LIBLIST); 2024 | NM(MIPS_MSYM); 2025 | NM(MIPS_CONFLICT); 2026 | NM(MIPS_GPTAB); 2027 | NM(MIPS_UCODE); 2028 | NM(MIPS_DEBUG); 2029 | NM(MIPS_REGINFO); 2030 | NM(MIPS_IFACE); 2031 | NM(MIPS_CONTENT); 2032 | NM(MIPS_OPTIONS); 2033 | NM(MIPS_DWARF); 2034 | NM(MIPS_SYMBOL_LIB); 2035 | NM(MIPS_EVENTS); 2036 | NM2(DVP_OVERLAY_TABLE, MIPS_DVP_OVERLAY_TABLE); 2037 | NM2(DVP_OVERLAY, MIPS_DVP_OVERLAY); 2038 | NM(MIPS_IOPMOD); 2039 | NM(MIPS_PSPREL); 2040 | } 2041 | } 2042 | else if ( m == EM_PPC64 ) 2043 | { 2044 | switch ( sh_type ) 2045 | { 2046 | NM2(PS3PRX_RELA, PRXRELA); 2047 | } 2048 | } 2049 | break; 2050 | } 2051 | } 2052 | static char buf[9]; 2053 | qsnprintf(buf, sizeof(buf), "%X", sh_type); 2054 | return buf; 2055 | #undef NM2 2056 | #undef NM 2057 | } 2058 | 2059 | //------------------------------------------------------------------------- 2060 | uint64 section_headers_t::get_size_in_file(const elf_shdr_t &sh) const 2061 | { 2062 | if ( sh.sh_type == SHT_NOBITS ) 2063 | return 0; 2064 | uint64 next_boundary = reader->size(); 2065 | // It may happen that we receive a section header that is _not_ part 2066 | // of the list of original section headers. E.g., when we load symbols 2067 | // from the dynamic-provided information. 2068 | const elf_shdr_t *next_sh = &sh + 1; 2069 | if ( next_sh >= begin() 2070 | && next_sh < end() 2071 | && next_sh->sh_offset >= sh.sh_offset ) 2072 | { 2073 | next_boundary = next_sh->sh_offset; 2074 | } 2075 | return qmin(sh.sh_size, next_boundary - sh.sh_offset); 2076 | } 2077 | 2078 | //------------------------------------------------------------------------- 2079 | void section_headers_t::read_file_contents( 2080 | bytevec_t *out, 2081 | const elf_shdr_t &sh) const 2082 | { 2083 | uint64 nbytes = get_size_in_file(sh); 2084 | out->resize(nbytes); 2085 | reader->seek(sh.sh_offset); 2086 | reader->safe_read(out->begin(), nbytes, /*apply_endianness=*/ false); 2087 | } 2088 | 2089 | 2090 | //------------------------------------------------------------------------- 2091 | // program_headers_t 2092 | //---------------------------------------------------------------------------- 2093 | const char *program_headers_t::p_type_str(uint32 p_type) const 2094 | { 2095 | #define NM(tp) case PT_##tp: return #tp 2096 | #define NM2(tp, nm) case PT_##tp: return #nm 2097 | 2098 | // OS-specific types 2099 | uint8 os_abi = reader->get_ident().osabi; 2100 | if ( os_abi == ELFOSABI_SOLARIS ) 2101 | { 2102 | switch ( p_type ) 2103 | { 2104 | NM2(SUNW_UNWIND, UNWIND); 2105 | NM2(SUNW_EH_FRAME, EH_FRAME); 2106 | NM(SUNWBSS); 2107 | NM2(SUNWSTACK, STACK); 2108 | NM2(SUNWDTRACE, DTRACE); 2109 | NM(SUNWCAP); 2110 | } 2111 | } 2112 | else 2113 | { 2114 | switch ( p_type ) 2115 | { 2116 | NM2(GNU_EH_FRAME, EH_FRAME); 2117 | NM2(GNU_STACK, STACK); 2118 | NM2(GNU_RELRO, RO-AFTER); 2119 | } 2120 | } 2121 | 2122 | switch ( p_type ) 2123 | { 2124 | NM(NULL); 2125 | NM(LOAD); 2126 | NM(DYNAMIC); 2127 | NM(INTERP); 2128 | NM(NOTE); 2129 | NM(SHLIB); 2130 | NM(PHDR); 2131 | NM(TLS); 2132 | 2133 | NM2(PAX_FLAGS, PAX-FLAG); 2134 | 2135 | default: 2136 | { 2137 | uint32 m = reader->get_header().e_machine; 2138 | if ( m == EM_ARM ) 2139 | { 2140 | switch ( p_type ) 2141 | { 2142 | NM2(ARM_ARCHEXT, ARCHEXT); 2143 | NM2(ARM_EXIDX, EXIDX); 2144 | } 2145 | } 2146 | else if ( m == EM_AARCH64 ) 2147 | { 2148 | switch ( p_type ) 2149 | { 2150 | NM2(AARCH64_ARCHEXT, ARCHEXT); 2151 | NM2(AARCH64_UNWIND, EXIDX); 2152 | } 2153 | } 2154 | else if ( m == EM_IA64 ) 2155 | { 2156 | switch ( p_type ) 2157 | { 2158 | NM(HP_TLS ); 2159 | NM(HP_CORE_NONE ); 2160 | NM(HP_CORE_VERSION ); 2161 | NM(HP_CORE_KERNEL ); 2162 | NM(HP_CORE_COMM ); 2163 | NM(HP_CORE_PROC ); 2164 | NM(HP_CORE_LOADABLE ); 2165 | NM(HP_CORE_STACK ); 2166 | NM(HP_CORE_SHM ); 2167 | NM(HP_CORE_MMF ); 2168 | NM(HP_PARALLEL ); 2169 | NM(HP_FASTBIND ); 2170 | NM(HP_OPT_ANNOT ); 2171 | NM(HP_HSL_ANNOT ); 2172 | NM(HP_STACK ); 2173 | NM(HP_CORE_UTSNAME ); 2174 | NM(HP_LINKER_FOOTPRINT ); 2175 | NM(IA_64_ARCHEXT ); 2176 | NM(IA_64_UNWIND ); 2177 | } 2178 | } 2179 | else if ( m == EM_MIPS ) 2180 | { 2181 | switch ( p_type ) 2182 | { 2183 | NM2(MIPS_IOPMOD, IOPMOD); 2184 | NM2(MIPS_EEMOD, EEMOD); 2185 | NM2(MIPS_PSPREL, PSPREL); 2186 | NM2(MIPS_PSPREL2, PSPREL2); 2187 | NM2(MIPS_REGINFO, REGINFO); 2188 | NM2(MIPS_RTPROC, RTPROC); 2189 | NM2(MIPS_OPTIONS, OPTIONS); 2190 | NM2(MIPS_ABIFLAGS, ABIFLAGS); 2191 | } 2192 | } 2193 | else if ( m == EM_PPC64 ) 2194 | { 2195 | switch ( p_type ) 2196 | { 2197 | case PHT_PS3PRX_RELA : return "PRXRELA"; 2198 | } 2199 | } 2200 | static char buf[10]; 2201 | qsnprintf(buf, sizeof(buf), "%08X", p_type); 2202 | return buf; 2203 | } 2204 | } 2205 | #undef NM2 2206 | #undef NM 2207 | } 2208 | 2209 | //---------------------------------------------------------------------------- 2210 | uint64 program_headers_t::get_size_in_file(const elf_phdr_t &p) const 2211 | { 2212 | assert_initialized(); 2213 | if ( p.p_type != PT_LOAD 2214 | && p.p_type != PT_INTERP 2215 | && p.p_type != PT_NOTE 2216 | && p.p_type != PT_PHDR ) 2217 | { 2218 | return 0; 2219 | } 2220 | 2221 | uint64 next_boundary = reader->size(); 2222 | if ( p.p_offset >= next_boundary ) 2223 | return 0; 2224 | 2225 | int idx = &p - begin(); 2226 | if ( idx > -1 && (idx+1) < pheaders.size() ) 2227 | { 2228 | const elf_phdr_t *np = CONST_CAST(program_headers_t*)(this)->get(idx+1); 2229 | if ( np->p_offset >= p.p_offset ) 2230 | next_boundary = np->p_offset; 2231 | } 2232 | return qmin(p.p_filesz, next_boundary - p.p_offset); 2233 | } 2234 | 2235 | //---------------------------------------------------------------------------- 2236 | void program_headers_t::read_file_contents( 2237 | bytevec_t *out, 2238 | const elf_phdr_t &p) const 2239 | { 2240 | assert_initialized(); 2241 | uint64 nbytes = get_size_in_file(p); 2242 | if ( nbytes == 0 ) 2243 | return; 2244 | out->resize(nbytes); 2245 | reader->seek(p.p_offset); 2246 | reader->safe_read(out->begin(), nbytes, /*apply_endianness=*/ false); 2247 | } 2248 | 2249 | //---------------------------------------------------------------------------- 2250 | // Note Section 2251 | // 2252 | bool elf_note_t::unpack_sz(uint32 *r, uint32 *start, const bytevec_t &buf, bool mf) 2253 | { 2254 | if ( *start + 4 > buf.size() ) 2255 | return false; 2256 | 2257 | uint32 res = *(uint32 *)&buf[*start]; 2258 | if ( mf ) 2259 | res = swap32(res); 2260 | if ( r != NULL ) 2261 | *r = res; 2262 | *start += 4; 2263 | return true; 2264 | } 2265 | 2266 | //---------------------------------------------------------------------------- 2267 | bool elf_note_t::unpack_strz(qstring *out, const bytevec_t &buf, uint32 start, uint32 len) 2268 | { 2269 | if ( start + len > buf.size() ) 2270 | return false; 2271 | out->qclear(); 2272 | out->reserve(len); 2273 | for ( int i=0; i < len; ++i ) 2274 | { 2275 | char ch = buf[start + i]; 2276 | if ( ch == '\0' ) 2277 | break; 2278 | out->append(ch); 2279 | } 2280 | return true; 2281 | } 2282 | 2283 | //---------------------------------------------------------------------------- 2284 | bool elf_note_t::unpack(elf_note_t *entry, uint32 *start, const bytevec_t &buf, bool mf) 2285 | { 2286 | 2287 | uint32 end = *start; 2288 | uint32 namesz; 2289 | uint32 descsz; 2290 | uint32 type; 2291 | if ( !elf_note_t::unpack_sz(&namesz, &end, buf, mf) 2292 | || !elf_note_t::unpack_sz(&descsz, &end, buf, mf) 2293 | || !elf_note_t::unpack_sz(&type, &end, buf, mf) ) 2294 | { 2295 | return false; 2296 | } 2297 | 2298 | qstring name; 2299 | if ( !elf_note_t::unpack_strz(&name, buf, end, namesz) ) 2300 | return false; 2301 | end += align_up(namesz, 4); 2302 | 2303 | qstring desc; 2304 | if ( !elf_note_t::unpack_strz(&desc, buf, end, descsz) ) 2305 | return false; 2306 | end += align_up(descsz, 4); 2307 | 2308 | if ( entry != NULL ) 2309 | { 2310 | entry->name = name; 2311 | entry->desc = desc; 2312 | entry->type = type; 2313 | } 2314 | *start = end; 2315 | return true; 2316 | } 2317 | 2318 | //---------------------------------------------------------------------------- 2319 | void notes_t::add(const bytevec_t &buf) 2320 | { 2321 | bool mf = reader->is_msb(); 2322 | uint32 start = 0; 2323 | while ( start < buf.size() ) 2324 | { 2325 | elf_note_t &n = notes.push_back(); 2326 | if ( !elf_note_t::unpack(&n, &start, buf, mf) ) 2327 | { 2328 | notes.pop_back(); 2329 | break; 2330 | } 2331 | } 2332 | } 2333 | 2334 | //---------------------------------------------------------------------------- 2335 | bool notes_t::get_build_id(qstring *out) 2336 | { 2337 | assert_initialized(); 2338 | 2339 | for ( elf_notes_t::const_iterator p=notes.begin(); p != notes.end(); ++p ) 2340 | { 2341 | const elf_note_t &en = *p; 2342 | if ( en.name == NT_NAME_GNU && en.type == NT_GNU_BUILD_ID ) 2343 | { 2344 | int sz = en.desc.length(); 2345 | out->qclear(); 2346 | out->reserve(2*sz); 2347 | for ( int i=0; i < sz; ++i ) 2348 | out->cat_sprnt("%02x", (unsigned char)en.desc[i]); 2349 | return true; 2350 | } 2351 | } 2352 | return false; 2353 | } 2354 | 2355 | //---------------------------------------------------------------------------- 2356 | template<> void buffered_input_t::start_reading() 2357 | { 2358 | reader.get_arch_specific()->on_start_symbols(reader); 2359 | } 2360 | 2361 | //---------------------------------------------------------------------------- 2362 | template<> bool buffered_input_t::read_item(sym_rel &storage) 2363 | { 2364 | storage = sym_rel(); 2365 | 2366 | elf_sym_t &orig = storage.original; 2367 | #define _safe(expr) \ 2368 | do \ 2369 | { \ 2370 | if ( expr < 0 ) \ 2371 | return false; \ 2372 | } while ( 0 ) 2373 | _safe(reader.read_symbol(&orig)); 2374 | 2375 | ushort bind = ELF_ST_BIND(orig.st_info); 2376 | // assert: bind <= STB_HIPROC 2377 | if ( bind > STB_WEAK ) 2378 | { 2379 | CASSERT(STB_LOCAL < STB_WEAK && STB_GLOBAL < STB_WEAK); //-V590 expression is excessive 2380 | if ( reader.get_header().e_machine == EM_ARM && bind == STB_LOPROC+1 ) 2381 | // codewarrior for arm seems to use this binding type similar to local or weak 2382 | bind = STB_WEAK; 2383 | else if ( bind < STB_LOOS ) 2384 | bind = STB_INVALID; 2385 | } 2386 | 2387 | storage.bind = (uchar) bind; 2388 | storage.sec = 0; 2389 | storage.type = ELF_ST_TYPE(orig.st_info); 2390 | storage.value = orig.st_value + reader.get_load_bias(); 2391 | storage.size = orig.st_size; 2392 | return true; 2393 | } 2394 | 2395 | //---------------------------------------------------------------------------- 2396 | static inline void swap_64_at(uint64 *ptr) 2397 | { 2398 | *ptr = swap64(*ptr); 2399 | } 2400 | 2401 | //---------------------------------------------------------------------------- 2402 | static inline void swap_64_at(int64 *ptr) 2403 | { 2404 | *ptr = swap64(*ptr); 2405 | } 2406 | 2407 | //---------------------------------------------------------------------------- 2408 | #define swap_addr(ptr) swap_64_at(ptr); 2409 | #define swap_xword(ptr) swap_64_at(ptr); 2410 | #define swap_sxword(ptr) swap_64_at(ptr); 2411 | 2412 | //---------------------------------------------------------------------------- 2413 | template<> ssize_t buffered_input_t::read_items(size_t max) 2414 | { 2415 | if ( isize != sizeof(Elf32_Rel) && isize != sizeof(Elf64_Rel) ) 2416 | return 0; 2417 | if ( !is_mul_ok(read, isize) || !is_mul_ok(max, isize) ) 2418 | return 0; 2419 | input_status_t save_excursion(reader); 2420 | if ( save_excursion.seek(offset + (read * isize)) == -1 ) 2421 | return 0; 2422 | memset(buffer, 0, sizeof(buffer)); 2423 | ssize_t bytes = max * isize; 2424 | QASSERT(20043, bytes <= sizeof(buffer)); 2425 | if ( qlread(reader.get_linput(), buffer, bytes) != bytes ) 2426 | return 0; 2427 | 2428 | #if __MF__ 2429 | bool swap = !reader.is_msb(); 2430 | #else 2431 | bool swap = reader.is_msb(); 2432 | #endif 2433 | 2434 | if ( isize == sizeof(Elf32_Rel) ) 2435 | { 2436 | Elf32_Rel *rel32 = (Elf32_Rel *) buffer; 2437 | Elf64_Rel *rel64 = (Elf64_Rel *) buffer; 2438 | rel32 += max - 1; 2439 | rel64 += max - 1; 2440 | uint64 inf64, off64; 2441 | for ( size_t i = 0; i < max; i++, rel32--, rel64-- ) 2442 | { 2443 | if ( swap ) 2444 | { 2445 | inf64 = swap32(rel32->r_info); 2446 | off64 = swap32(rel32->r_offset); 2447 | } 2448 | else 2449 | { 2450 | inf64 = rel32->r_info; 2451 | off64 = rel32->r_offset; 2452 | } 2453 | rel64->r_info = inf64; 2454 | rel64->r_offset = off64; 2455 | } 2456 | } 2457 | else 2458 | { 2459 | if ( swap ) 2460 | { 2461 | elf_rel_t *rel64 = buffer; 2462 | for ( size_t i = 0; i < max; i++, rel64++ ) 2463 | { 2464 | swap_addr(&rel64->r_offset); 2465 | swap_xword(&rel64->r_info); 2466 | } 2467 | } 2468 | } 2469 | 2470 | return max; 2471 | } 2472 | 2473 | //---------------------------------------------------------------------------- 2474 | template<> ssize_t buffered_input_t::read_items(size_t max) 2475 | { 2476 | if ( isize != sizeof(Elf32_Rela) && isize != sizeof(Elf64_Rela) ) 2477 | return 0; 2478 | if ( !is_mul_ok(read, isize) || !is_mul_ok(max, isize) ) 2479 | return 0; 2480 | input_status_t save_excursion(reader); 2481 | if ( save_excursion.seek(offset + (read * isize)) == -1 ) 2482 | return 0; 2483 | memset(buffer, 0, sizeof(buffer)); 2484 | ssize_t bytes = max * isize; 2485 | QASSERT(20044, bytes <= sizeof(buffer)); 2486 | if ( qlread(reader.get_linput(), buffer, bytes) != bytes ) 2487 | return 0; 2488 | 2489 | #if __MF__ 2490 | bool swap = !reader.is_msb(); 2491 | #else 2492 | bool swap = reader.is_msb(); 2493 | #endif 2494 | 2495 | if ( isize == sizeof(Elf32_Rela) ) 2496 | { 2497 | Elf32_Rela *rela32 = (Elf32_Rela *) buffer; 2498 | Elf64_Rela *rela64 = (Elf64_Rela *) buffer; 2499 | rela32 += max - 1; 2500 | rela64 += max - 1; 2501 | uint64 inf64, off64; 2502 | int64 addend; 2503 | for ( size_t i = 0; i < max; i++, rela32--, rela64-- ) 2504 | { 2505 | if ( swap ) 2506 | { 2507 | inf64 = swap32(rela32->r_info); 2508 | off64 = swap32(rela32->r_offset); 2509 | addend = swap32(rela32->r_addend); 2510 | } 2511 | else 2512 | { 2513 | inf64 = rela32->r_info; 2514 | off64 = rela32->r_offset; 2515 | addend = rela32->r_addend; 2516 | } 2517 | rela64->r_info = inf64; 2518 | rela64->r_offset = off64; 2519 | rela64->r_addend = addend; 2520 | } 2521 | } 2522 | else 2523 | { 2524 | if ( swap ) 2525 | { 2526 | elf_rela_t *rela64 = buffer; 2527 | for ( size_t i = 0; i < max; i++, rela64++ ) 2528 | { 2529 | swap_addr(&rela64->r_offset); 2530 | swap_xword(&rela64->r_info); 2531 | swap_sxword(&rela64->r_addend); 2532 | } 2533 | } 2534 | } 2535 | 2536 | return max; 2537 | } 2538 | 2539 | //---------------------------------------------------------------------------- 2540 | template<> bool buffered_input_t::read_item(elf_dyn_t &storage) 2541 | { 2542 | // FIXME: Load bias? 2543 | memset(&storage, 0, sizeof(storage)); 2544 | _safe(reader.read_sxword(&storage.d_tag)); 2545 | _safe(reader.read_addr(&storage.d_un)); 2546 | #undef _safe 2547 | return true; 2548 | } 2549 | 2550 | //------------------------------------------------------------------------- 2551 | void dynamic_info_t::initialize(const reader_t &reader) 2552 | { 2553 | symtab().entsize = reader.stdsizes.entries.sym; 2554 | rel().entsize = reader.stdsizes.dyn.rel; 2555 | rela().entsize = reader.stdsizes.dyn.rela; 2556 | QASSERT(20037, symtab().entsize != 0 && rel().entsize != 0 && rela().entsize != 0); 2557 | } 2558 | 2559 | //---------------------------------------------------------------------------- 2560 | bool dynamic_info_t::fill_section_header( 2561 | elf_shdr_t *sh, 2562 | dynamic_info_type_t type) const 2563 | { 2564 | switch ( type ) 2565 | { 2566 | case DIT_SYMTAB: 2567 | case DIT_REL: 2568 | case DIT_RELA: 2569 | case DIT_PLT: 2570 | case DIT_VERDEF: 2571 | case DIT_VERNEED: 2572 | case DIT_VERSYM: 2573 | break; 2574 | default: 2575 | QASSERT(20101, false); 2576 | }; 2577 | const entry_t &entry = entries[type]; 2578 | if ( !entry.is_valid() ) 2579 | return false; 2580 | memset(sh, 0, sizeof(*sh)); 2581 | sh->sh_addr = entry.addr; 2582 | sh->sh_offset = entry.offset; 2583 | sh->sh_size = entry.size; 2584 | sh->sh_info = entry.info; 2585 | sh->sh_type = type == DIT_SYMTAB ? SHT_DYNSYM 2586 | : type == DIT_RELA ? SHT_RELA 2587 | : type == DIT_REL ? SHT_REL 2588 | : type == DIT_VERDEF ? SHT_GNU_verdef 2589 | : type == DIT_VERNEED ? SHT_GNU_verneed 2590 | : type == DIT_VERSYM ? SHT_GNU_versym 2591 | : plt_rel_type == DT_RELA ? SHT_RELA 2592 | : SHT_REL; 2593 | sh->sh_entsize = sh->sh_type == SHT_DYNSYM ? entry.entsize 2594 | : sh->sh_type == SHT_RELA ? rela().entsize 2595 | : rel().entsize; 2596 | return true; 2597 | } 2598 | 2599 | //---------------------------------------------------------------------------- 2600 | const char *dynamic_info_t::d_tag_str_ext(const reader_t &reader, int64 d_tag) 2601 | { 2602 | static qstring buf; 2603 | buf = d_tag_str(reader, d_tag); 2604 | if ( buf.empty() ) 2605 | { 2606 | buf.sprnt("DT_???? Unknown (%08" FMT_64 "X)", d_tag); 2607 | return buf.begin(); 2608 | } 2609 | if ( buf.length() < 12 ) 2610 | buf.resize(12, ' '); 2611 | 2612 | uint16 e_machine = reader.get_header().e_machine; 2613 | const char *ext = NULL; 2614 | switch ( d_tag ) 2615 | { 2616 | case DT_NULL: 2617 | ext = "end of _DYNAMIC array"; 2618 | break; 2619 | case DT_NEEDED: 2620 | ext = "str-table offset name to needed library"; 2621 | break; 2622 | case DT_PLTRELSZ: 2623 | ext = "tot.size in bytes of relocation entries"; 2624 | break; 2625 | case DT_HASH: 2626 | ext = "addr. of symbol hash table"; 2627 | break; 2628 | case DT_STRTAB: 2629 | ext = "addr of string table"; 2630 | break; 2631 | case DT_SYMTAB: 2632 | ext = "addr of symbol table"; 2633 | break; 2634 | case DT_RELA: 2635 | ext = "addr of relocation table"; 2636 | break; 2637 | case DT_RELASZ: 2638 | ext = "size in bytes of DT_RELA table"; 2639 | break; 2640 | case DT_RELAENT: 2641 | ext = "size in bytes of DT_RELA entry"; 2642 | break; 2643 | case DT_STRSZ: 2644 | ext = "size in bytes of string table"; 2645 | break; 2646 | case DT_SYMENT: 2647 | ext = "size in bytes of symbol table entry"; 2648 | break; 2649 | case DT_INIT: 2650 | ext = "addr. of initialization function"; 2651 | break; 2652 | case DT_FINI: 2653 | ext = "addr. of termination function"; 2654 | break; 2655 | case DT_SONAME: 2656 | ext = "offs in str.-table - name of shared object"; 2657 | break; 2658 | case DT_RPATH: 2659 | ext = "offs in str-table - search path"; 2660 | break; 2661 | case DT_RUNPATH: 2662 | ext = "array of search pathes"; 2663 | break; 2664 | case DT_SYMBOLIC: 2665 | ext = "start search of shared object"; 2666 | break; 2667 | case DT_REL: 2668 | ext = "addr of relocation table"; 2669 | break; 2670 | case DT_RELSZ: 2671 | ext = "tot.size in bytes of DT_REL"; 2672 | break; 2673 | case DT_RELENT: 2674 | ext = "size in bytes of DT_REL entry"; 2675 | break; 2676 | case DT_PLTREL: 2677 | ext = "type of relocation (DT_REL or DT_RELA)"; 2678 | break; 2679 | case DT_DEBUG: 2680 | ext = "not specified"; 2681 | break; 2682 | case DT_TEXTREL: 2683 | ext = "segment permisson"; 2684 | break; 2685 | case DT_PLTGOT: 2686 | if ( e_machine == EM_PPC ) 2687 | ext = "addr of PLT"; 2688 | break; 2689 | case DT_JMPREL: 2690 | if ( e_machine == EM_PPC ) 2691 | ext = "addr of JMP_SLOT relocation table"; 2692 | else 2693 | ext = "addr of dlt procedure (if present)"; 2694 | break; 2695 | case DT_PPC_GOT: 2696 | if ( e_machine == EM_PPC ) 2697 | ext = "addr of _GLOBAL_OFFSET_TABLE_"; 2698 | break; 2699 | } 2700 | return buf.append(ext).begin(); 2701 | } 2702 | 2703 | //---------------------------------------------------------------------------- 2704 | const char *dynamic_info_t::d_tag_str(const reader_t &reader, int64 d_tag) 2705 | { 2706 | uint16 e_machine = reader.get_header().e_machine; 2707 | #define NM(tp) case tp: return #tp 2708 | 2709 | // OS-specific types 2710 | uint8 os_abi = reader.get_ident().osabi; 2711 | if ( os_abi == ELFOSABI_SOLARIS ) 2712 | { 2713 | switch ( d_tag ) 2714 | { 2715 | NM(DT_SUNW_AUXILIARY); 2716 | // NM(DT_SUNW_RTLDINF); 2717 | NM(DT_SUNW_FILTER); 2718 | NM(DT_SUNW_CAP); 2719 | NM(DT_SUNW_SYMTAB); 2720 | NM(DT_SUNW_SYMSZ); 2721 | NM(DT_SUNW_ENCODING); 2722 | // NM(DT_SUNW_SORTENT); 2723 | NM(DT_SUNW_SYMSORT); 2724 | NM(DT_SUNW_SYMSORTSZ); 2725 | NM(DT_SUNW_TLSSORT); 2726 | NM(DT_SUNW_TLSSORTSZ); 2727 | NM(DT_SUNW_CAPINFO); 2728 | NM(DT_SUNW_STRPAD); 2729 | NM(DT_SUNW_CAPCHAIN); 2730 | NM(DT_SUNW_LDMACH); 2731 | NM(DT_SUNW_CAPCHAINENT); 2732 | NM(DT_SUNW_CAPCHAINSZ); 2733 | NM(DT_SUNW_PARENT); 2734 | NM(DT_SUNW_ASLR); 2735 | NM(DT_SUNW_RELAX); 2736 | NM(DT_SUNW_NXHEAP); 2737 | NM(DT_SUNW_NXSTACK); 2738 | } 2739 | } 2740 | 2741 | switch ( d_tag ) 2742 | { 2743 | NM(DT_NULL); 2744 | NM(DT_NEEDED); 2745 | NM(DT_PLTRELSZ); 2746 | NM(DT_HASH); 2747 | NM(DT_STRTAB); 2748 | NM(DT_SYMTAB); 2749 | NM(DT_RELA); 2750 | NM(DT_RELASZ); 2751 | NM(DT_RELAENT); 2752 | NM(DT_STRSZ); 2753 | NM(DT_SYMENT); 2754 | NM(DT_INIT); 2755 | NM(DT_FINI); 2756 | NM(DT_SONAME); 2757 | NM(DT_RPATH); 2758 | NM(DT_RUNPATH); 2759 | NM(DT_SYMBOLIC); 2760 | NM(DT_REL); 2761 | NM(DT_RELSZ); 2762 | NM(DT_RELENT); 2763 | NM(DT_PLTREL); 2764 | NM(DT_DEBUG); 2765 | NM(DT_TEXTREL); 2766 | 2767 | NM(DT_PLTGOT); 2768 | NM(DT_JMPREL); 2769 | 2770 | NM(DT_BIND_NOW); 2771 | NM(DT_PREINIT_ARRAY); 2772 | NM(DT_INIT_ARRAY); 2773 | NM(DT_FINI_ARRAY); 2774 | NM(DT_INIT_ARRAYSZ); 2775 | NM(DT_FINI_ARRAYSZ); 2776 | NM(DT_PREINIT_ARRAYSZ); 2777 | NM(DT_FLAGS); 2778 | 2779 | NM(DT_VALRNGLO); 2780 | NM(DT_GNU_PRELINKED); 2781 | NM(DT_GNU_CONFLICTSZ); 2782 | NM(DT_GNU_LIBLISTSZ); 2783 | NM(DT_CHECKSUM); 2784 | NM(DT_PLTPADSZ); 2785 | NM(DT_MOVEENT); 2786 | NM(DT_MOVESZ); 2787 | NM(DT_FEATURE); 2788 | NM(DT_POSFLAG_1); 2789 | NM(DT_SYMINSZ); 2790 | NM(DT_SYMINENT); 2791 | // NM(DT_VALRNGHI); 2792 | NM(DT_ADDRRNGLO); 2793 | NM(DT_GNU_HASH); 2794 | NM(DT_TLSDESC_PLT); 2795 | NM(DT_TLSDESC_GOT); 2796 | NM(DT_GNU_CONFLICT); 2797 | NM(DT_GNU_LIBLIST); 2798 | NM(DT_CONFIG); 2799 | NM(DT_DEPAUDIT); 2800 | NM(DT_AUDIT); 2801 | NM(DT_PLTPAD); 2802 | NM(DT_MOVETAB); 2803 | NM(DT_SYMINFO); 2804 | // NM(DT_ADDRRNGHI); 2805 | NM(DT_RELACOUNT); 2806 | NM(DT_RELCOUNT); 2807 | NM(DT_FLAGS_1); 2808 | NM(DT_VERDEF); 2809 | NM(DT_VERDEFNUM); 2810 | NM(DT_VERNEED); 2811 | NM(DT_VERNEEDNUM); 2812 | NM(DT_VERSYM); 2813 | 2814 | NM(DT_AUXILIARY); 2815 | NM(DT_USED); 2816 | NM(DT_FILTER); 2817 | } 2818 | if ( e_machine == EM_MIPS ) 2819 | { 2820 | switch ( d_tag ) 2821 | { 2822 | NM(DT_MIPS_RLD_VERSION); 2823 | NM(DT_MIPS_TIME_STAMP); 2824 | NM(DT_MIPS_ICHECKSUM); 2825 | NM(DT_MIPS_IVERSION); 2826 | NM(DT_MIPS_FLAGS); 2827 | NM(DT_MIPS_BASE_ADDRESS); 2828 | NM(DT_MIPS_MSYM); 2829 | NM(DT_MIPS_CONFLICT); 2830 | NM(DT_MIPS_LIBLIST); 2831 | NM(DT_MIPS_LOCAL_GOTNO); 2832 | NM(DT_MIPS_CONFLICTNO); 2833 | NM(DT_MIPS_LIBLISTNO); 2834 | NM(DT_MIPS_SYMTABNO); 2835 | NM(DT_MIPS_UNREFEXTNO); 2836 | NM(DT_MIPS_GOTSYM); 2837 | NM(DT_MIPS_HIPAGENO); 2838 | NM(DT_MIPS_RLD_MAP); 2839 | NM(DT_MIPS_DELTA_CLASS); 2840 | NM(DT_MIPS_DELTA_CLASS_NO); 2841 | NM(DT_MIPS_DELTA_INSTANCE); 2842 | NM(DT_MIPS_DELTA_INSTANCE_NO); 2843 | NM(DT_MIPS_DELTA_RELOC); 2844 | NM(DT_MIPS_DELTA_RELOC_NO); 2845 | NM(DT_MIPS_DELTA_SYM); 2846 | NM(DT_MIPS_DELTA_SYM_NO); 2847 | NM(DT_MIPS_DELTA_CLASSSYM); 2848 | NM(DT_MIPS_DELTA_CLASSSYM_NO); 2849 | NM(DT_MIPS_CXX_FLAGS); 2850 | NM(DT_MIPS_PIXIE_INIT); 2851 | NM(DT_MIPS_SYMBOL_LIB); 2852 | NM(DT_MIPS_LOCALPAGE_GOTIDX); 2853 | NM(DT_MIPS_LOCAL_GOTIDX); 2854 | NM(DT_MIPS_HIDDEN_GOTIDX); 2855 | NM(DT_MIPS_PROTECTED_GOTIDX); 2856 | NM(DT_MIPS_OPTIONS); 2857 | NM(DT_MIPS_INTERFACE); 2858 | NM(DT_MIPS_DYNSTR_ALIGN); 2859 | NM(DT_MIPS_INTERFACE_SIZE); 2860 | NM(DT_MIPS_RLD_TEXT_RESOLVE_ADDR); 2861 | NM(DT_MIPS_PERF_SUFFIX); 2862 | NM(DT_MIPS_COMPACT_SIZE); 2863 | NM(DT_MIPS_GP_VALUE); 2864 | NM(DT_MIPS_AUX_DYNAMIC); 2865 | NM(DT_MIPS_PLTGOT); 2866 | NM(DT_MIPS_RWPLT); 2867 | } 2868 | } 2869 | else if ( e_machine == EM_IA64 ) 2870 | { 2871 | switch ( d_tag ) 2872 | { 2873 | NM(DT_HP_LOAD_MAP); 2874 | NM(DT_HP_DLD_FLAGS); 2875 | NM(DT_HP_DLD_HOOK); 2876 | NM(DT_HP_UX10_INIT); 2877 | NM(DT_HP_UX10_INITSZ); 2878 | NM(DT_HP_PREINIT); 2879 | NM(DT_HP_PREINITSZ); 2880 | NM(DT_HP_NEEDED); 2881 | NM(DT_HP_TIME_STAMP); 2882 | NM(DT_HP_CHECKSUM); 2883 | NM(DT_HP_GST_SIZE); 2884 | NM(DT_HP_GST_VERSION); 2885 | NM(DT_HP_GST_HASHVAL); 2886 | NM(DT_HP_EPLTREL); 2887 | NM(DT_HP_EPLTRELSZ); 2888 | NM(DT_HP_FILTERED); 2889 | NM(DT_HP_FILTER_TLS); 2890 | NM(DT_HP_COMPAT_FILTERED); 2891 | NM(DT_HP_LAZYLOAD); 2892 | NM(DT_HP_BIND_NOW_COUNT); 2893 | NM(DT_PLT); 2894 | NM(DT_PLT_SIZE); 2895 | NM(DT_DLT); 2896 | NM(DT_DLT_SIZE); 2897 | NM(DT_HP_SYM_CHECKSUM); 2898 | NM(DT_IA_64_PLT_RESERVE); 2899 | } 2900 | } 2901 | else if ( e_machine == EM_PPC ) 2902 | { 2903 | switch ( d_tag ) 2904 | { 2905 | NM(DT_PPC_GOT); 2906 | } 2907 | } 2908 | #undef NM 2909 | return NULL; 2910 | } 2911 | 2912 | //---------------------------------------------------------------------------- 2913 | const char *dynamic_info_t::d_un_str(const reader_t &reader, int64 d_tag, int64 d_un) 2914 | { 2915 | static qstring name; 2916 | name.qclear(); 2917 | switch ( d_tag ) 2918 | { 2919 | case DT_SONAME: 2920 | case DT_RPATH: 2921 | case DT_RUNPATH: 2922 | case DT_NEEDED: 2923 | case DT_AUXILIARY: 2924 | case DT_FILTER: 2925 | case DT_CONFIG: 2926 | case DT_DEPAUDIT: 2927 | case DT_AUDIT: 2928 | reader.get_name(&name, reader.dyn_strtab, uint32(d_un)); 2929 | break; 2930 | } 2931 | return name.c_str(); 2932 | } 2933 | 2934 | //---------------------------------------------------------------------------- 2935 | size_t symrel_cache_t::slice_start(slice_type_t t) const 2936 | { 2937 | check_type(t); 2938 | return t == SLT_DYNSYM ? dynsym_index : 0; 2939 | } 2940 | 2941 | //---------------------------------------------------------------------------- 2942 | size_t symrel_cache_t::slice_end(slice_type_t t) const 2943 | { 2944 | check_type(t); 2945 | return t == SLT_SYMTAB ? dynsym_index : storage.size(); 2946 | } 2947 | 2948 | //---------------------------------------------------------------------------- 2949 | sym_rel &symrel_cache_t::append(slice_type_t t) 2950 | { 2951 | check_type(t); 2952 | size_t idx = slice_end(t); 2953 | if ( t == SLT_SYMTAB ) 2954 | ++dynsym_index; 2955 | if ( idx == storage.size() ) 2956 | { 2957 | return storage.push_back(); 2958 | } 2959 | else 2960 | { 2961 | qvector::iterator it = storage.begin() + idx; 2962 | storage.insert(it, sym_rel()); 2963 | return *it; 2964 | } 2965 | } 2966 | 2967 | 2968 | // =========================================================================== 2969 | // ARM-specific code. 2970 | // =========================================================================== 2971 | 2972 | 2973 | //---------------------------------------------------------------------------- 2974 | bool arm_arch_specific_t::is_mapping_symbol(const char *name) const 2975 | { 2976 | if ( name == NULL ) 2977 | return false; 2978 | 2979 | if ( name[0] == '$' 2980 | && (name[2] == '\0' || name[2] == '.') ) 2981 | { 2982 | switch ( name[1] ) 2983 | { 2984 | case 'a': // labels the first byte of a sequence of ARM instructions. Its type is STT_FUNC. 2985 | case 't': // labels the first byte of a sequence of Thumb instructions. Its type is STT_FUNC. 2986 | case 'b': // labels a Thumb BL instruction. Its type is STT_FUNC. 2987 | case 'd': // labels the first byte of a sequence of data items. Its type is STT_OBJECT. 2988 | case 'p': // labels the final, PC-modifying instruction of an 2989 | // indirect function call. Its type is STT_FUNC. 2990 | // (An indirect call is a call through a function pointer 2991 | // variable). $p does not label the PC-modifying 2992 | // instruction of a function return sequence. 2993 | case 'f': // labels a function pointer constant (static pointer to code). 2994 | // Its type is STT_OBJECT. 2995 | case 'x': // Start of a sequence of A64 instructions 2996 | return true; 2997 | } 2998 | } 2999 | return false; 3000 | } 3001 | 3002 | //---------------------------------------------------------------------------- 3003 | void arm_arch_specific_t::on_start_symbols(reader_t &) 3004 | { 3005 | has_mapsym = false; 3006 | } 3007 | 3008 | //---------------------------------------------------------------------------- 3009 | void arm_arch_specific_t::on_symbol_read(reader_t &reader, sym_rel &sym) 3010 | { 3011 | const char *name = sym.get_original_name(reader).c_str(); 3012 | if ( is_mapping_symbol(name) ) 3013 | { 3014 | has_mapsym = true; 3015 | 3016 | // assert: name != NULL 3017 | char name1 = name[1]; 3018 | if ( name1 == 'a' || name1 == 't' || name1 == 'x' ) 3019 | { 3020 | isa_t isa = name1 == 'a' || name1 == 'x' ? isa_arm : isa_thumb; 3021 | sym.set_flag(thumb_function); // FIXME: Shouldn't we check 'a' or 't', here? 3022 | // FIXME: Shouldn't it be reversed, too? 3023 | notify_isa(reader, sym, isa, true); 3024 | if ( is_mapping_symbols_tracking() ) 3025 | set_isa(sym, isa); 3026 | } 3027 | } 3028 | else 3029 | { 3030 | uchar bind = sym.bind; 3031 | 3032 | // Keep going _only_ if function 3033 | ushort orig_type = ELF_ST_TYPE(sym.original.st_info); 3034 | if ( (orig_type != STT_FUNC 3035 | && orig_type != STT_ARM_TFUNC 3036 | && orig_type != STT_ARM_16BIT ) 3037 | || (bind != STB_GLOBAL 3038 | && bind != STB_LOCAL 3039 | && bind != STB_WEAK) ) 3040 | { 3041 | return; 3042 | } 3043 | 3044 | sym.value &= ~1; 3045 | 3046 | // If original type is ARM_TFUNC, make it FUNC, 3047 | // so it gets treated as a regular FUNC by 3048 | // upstream code. 3049 | if ( orig_type == STT_ARM_TFUNC ) 3050 | sym.type = STT_FUNC; 3051 | 3052 | if ( (orig_type == STT_ARM_TFUNC 3053 | || orig_type == STT_ARM_16BIT 3054 | || (sym.original.st_value & 1) != 0) ) 3055 | { 3056 | sym.set_flag(thumb_function); 3057 | notify_isa(reader, sym, isa_thumb, false); 3058 | } 3059 | 3060 | if ( !sym.has_flag(thumb_function) 3061 | && is_mapping_symbols_tracking() 3062 | && get_isa(sym) == isa_thumb ) 3063 | { 3064 | sym.set_flag(thumb_function); 3065 | notify_isa(reader, sym, isa_thumb, false); 3066 | } 3067 | 3068 | if ( !sym.has_flag(thumb_function) ) 3069 | notify_isa(reader, sym, isa_arm, false); 3070 | } 3071 | } 3072 | 3073 | //---------------------------------------------------------------------------- 3074 | void arm_arch_specific_t::set_isa(const sym_rel &symbol, isa_t isa) 3075 | { 3076 | isa_ranges_t::iterator it = isa_ranges.find(symbol.sec); 3077 | if ( it == isa_ranges.end() ) 3078 | { 3079 | isa_ranges[symbol.sec] = section_isa_ranges_t(); 3080 | it = isa_ranges.find(symbol.sec); 3081 | } 3082 | 3083 | section_isa_ranges_t §ion_isa_ranges = it->second; 3084 | section_isa_ranges[symbol.original.st_value] = isa; 3085 | } 3086 | 3087 | //---------------------------------------------------------------------------- 3088 | arm_arch_specific_t::isa_t arm_arch_specific_t::get_isa(const sym_rel &symbol) const 3089 | { 3090 | isa_t current_isa = isa_arm; 3091 | isa_ranges_t::const_iterator it = isa_ranges.find(symbol.sec); 3092 | if ( it != isa_ranges.end() ) 3093 | { 3094 | const section_isa_ranges_t §ion_isa_ranges = it->second; 3095 | section_isa_ranges_t::const_iterator p; 3096 | section_isa_ranges_t::const_iterator end = section_isa_ranges.end(); 3097 | for ( p = section_isa_ranges.begin(); p != end; ++p ) 3098 | { 3099 | uint64 offset_in_section = p->first; 3100 | if ( offset_in_section > symbol.original.st_value ) 3101 | break; 3102 | 3103 | current_isa = p->second; 3104 | } 3105 | } 3106 | return current_isa; 3107 | } 3108 | 3109 | #endif // ELF_READER_CPP 3110 | --------------------------------------------------------------------------------