1 // Copyright (c) 2012- PPSSPP Project.
2 
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, version 2.0 or later versions.
6 
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 // GNU General Public License 2.0 for more details.
11 
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
14 
15 // Official git repository and contact information can be found at
16 // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
17 
18 #pragma once
19 
20 #include <vector>
21 #include "Common/CommonTypes.h"
22 #include "Core/ELF/ElfTypes.h"
23 
24 enum {
25 	R_MIPS_NONE,
26 	R_MIPS_16,
27 	R_MIPS_32,
28 	R_MIPS_REL32,
29 	R_MIPS_26,
30 	R_MIPS_HI16,
31 	R_MIPS_LO16,
32 	R_MIPS_GPREL16,
33 	R_MIPS_LITERAL,
34 	R_MIPS_GOT16,
35 	R_MIPS_PC16,
36 	R_MIPS_CALL16,
37 	R_MIPS_GPREL32
38 };
39 
40 enum KnownElfTypes {
41 	KNOWNELF_PSP = 0,
42 	KNOWNELF_DS = 1,
43 	KNOWNELF_GBA = 2,
44 };
45 
46 typedef int SectionID;
47 
48 class ElfReader {
49 public:
ElfReader(const void * ptr,size_t size)50 	ElfReader(const void *ptr, size_t size) {
51 		base = (const char*)ptr;
52 		base32 = (const u32 *)ptr;
53 		header = (const Elf32_Ehdr*)ptr;
54 		segments = (const Elf32_Phdr *)(base + header->e_phoff);
55 		sections = (const Elf32_Shdr *)(base + header->e_shoff);
56 		size_ = size;
57 	}
58 
~ElfReader()59 	~ElfReader() {
60 		delete[] sectionOffsets;
61 		delete[] sectionAddrs;
62 	}
63 
Read32(int off)64 	u32 Read32(int off) const {
65 		return base32[off >> 2];
66 	}
67 
68 	// Quick accessors
GetType()69 	ElfType GetType() const { return (ElfType)(u16)(header->e_type); }
GetMachine()70 	ElfMachine GetMachine() const { return (ElfMachine)(u16)(header->e_machine); }
GetEntryPoint()71 	u32 GetEntryPoint() const { return entryPoint; }
GetFlags()72 	u32 GetFlags() const { return (u32)(header->e_flags); }
73 
GetNumSegments()74 	int GetNumSegments() const { return (int)(header->e_phnum); }
GetNumSections()75 	int GetNumSections() const { return (int)(header->e_shnum); }
76 	const char *GetSectionName(int section) const;
GetPtr(u32 offset)77 	const u8 *GetPtr(u32 offset) const {
78 		return (const u8*)base + offset;
79 	}
GetSectionDataPtr(int section)80 	const u8 *GetSectionDataPtr(int section) const {
81 		if (section < 0 || section >= header->e_shnum)
82 			return nullptr;
83 		if (sections[section].sh_type != SHT_NOBITS)
84 			return GetPtr(sections[section].sh_offset);
85 		else
86 			return nullptr;
87 	}
GetSegmentPtr(int segment)88 	const u8 *GetSegmentPtr(int segment) const {
89 		return GetPtr(segments[segment].p_offset);
90 	}
GetSectionAddr(SectionID section)91 	u32 GetSectionAddr(SectionID section) const {
92 		return sectionAddrs[section];
93 	}
GetSectionSize(SectionID section)94 	int GetSectionSize(SectionID section) const {
95 		return sections[section].sh_size;
96 	}
97 
98 	//-1 for not found
99 	SectionID GetSectionByName(const char *name, int firstSection = 0) const;
100 
GetSegmentPaddr(int segment)101 	u32 GetSegmentPaddr(int segment) const {
102 		return segments[segment].p_paddr;
103 	}
GetSegmentOffset(int segment)104 	u32 GetSegmentOffset(int segment) const {
105 		return segments[segment].p_offset;
106 	}
GetSegmentVaddr(int segment)107 	u32 GetSegmentVaddr(int segment) const {
108 		return segmentVAddr[segment];
109 	}
GetSegmentDataSize(int segment)110 	u32 GetSegmentDataSize(int segment) const {
111 		return segments[segment].p_filesz;
112 	}
GetSegmentMemSize(int segment)113 	u32 GetSegmentMemSize(int segment) const {
114 		return segments[segment].p_memsz;
115 	}
116 
GetFirstSegmentAlign()117 	u32 GetFirstSegmentAlign() const {
118 		return firstSegAlign;
119 	}
120 
DidRelocate()121 	bool DidRelocate() const {
122 		return bRelocate;
123 	}
124 
GetVaddr()125 	u32 GetVaddr() const {
126 		return vaddr;
127 	}
128 
GetTotalSize()129 	u32 GetTotalSize() const {
130 		return totalSize;
131 	}
132 
133 	u32 GetTotalTextSize() const;
134 	u32 GetTotalTextSizeFromSeg() const;
135 	u32 GetTotalDataSize() const;
136 	u32 GetTotalSectionSizeByPrefix(const std::string &prefix) const;
137 
138 	std::vector<SectionID> GetCodeSections() const;
139 
140 	int LoadInto(u32 vaddr, bool fromTop);
141 	bool LoadSymbols();
142 	bool LoadRelocations(const Elf32_Rel *rels, int numRelocs);
143 	void LoadRelocations2(int rel_seg);
144 
145 private:
146 	const char *base = nullptr;
147 	const u32 *base32 = nullptr;
148 	const Elf32_Ehdr *header = nullptr;
149 	const Elf32_Phdr *segments = nullptr;
150 	const Elf32_Shdr *sections = nullptr;
151 	u32 *sectionOffsets = nullptr;
152 	u32 *sectionAddrs = nullptr;
153 	bool bRelocate = false;
154 	u32 entryPoint = 0;
155 	u32 totalSize = 0;
156 	u32 vaddr = 0;
157 	u32 segmentVAddr[32];
158 	size_t size_ = 0;
159 	u32 firstSegAlign = 0;
160 };
161