Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(482)

Side by Side Diff: courgette/disassembler_elf_32_x86.cc

Issue 1676683002: [Courgette] Clean up Disassembler; fix ELF Memory leaks. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Wrap #include <iostream> under #if COURGETTE_HISTOGRAM_TARGETS. Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « courgette/disassembler_elf_32_x86.h ('k') | courgette/disassembler_elf_32_x86_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "courgette/disassembler_elf_32_x86.h" 5 #include "courgette/disassembler_elf_32_x86.h"
6 6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include <algorithm>
11 #include <string>
12 #include <vector> 7 #include <vector>
13 8
14 #include "base/logging.h" 9 #include "base/logging.h"
15 10 #include "base/memory/scoped_ptr.h"
16 #include "courgette/assembly_program.h" 11 #include "courgette/assembly_program.h"
17 #include "courgette/courgette.h" 12 #include "courgette/courgette.h"
18 #include "courgette/encoded_program.h"
19 13
20 namespace courgette { 14 namespace courgette {
21 15
22 DisassemblerElf32X86::DisassemblerElf32X86(const void* start, size_t length) 16 CheckBool DisassemblerElf32X86::TypedRVAX86::ComputeRelativeTarget(
23 : DisassemblerElf32(start, length) { 17 const uint8_t* op_pointer) {
18 set_relative_target(Read32LittleEndian(op_pointer) + 4);
19 return true;
24 } 20 }
25 21
26 // Convert an ELF relocation struction into an RVA 22 CheckBool DisassemblerElf32X86::TypedRVAX86::EmitInstruction(
23 AssemblyProgram* program,
24 RVA target_rva) {
25 return program->EmitRel32(program->FindOrMakeRel32Label(target_rva));
26 }
27
28 uint16_t DisassemblerElf32X86::TypedRVAX86::op_size() const {
29 return 4;
30 }
31
32 DisassemblerElf32X86::DisassemblerElf32X86(const void* start, size_t length)
33 : DisassemblerElf32(start, length) {
34 }
35
36 // Convert an ELF relocation struction into an RVA.
27 CheckBool DisassemblerElf32X86::RelToRVA(Elf32_Rel rel, RVA* result) const { 37 CheckBool DisassemblerElf32X86::RelToRVA(Elf32_Rel rel, RVA* result) const {
38 // The rightmost byte of r_info is the type.
39 elf32_rel_386_type_values type =
40 static_cast<elf32_rel_386_type_values>(rel.r_info & 0xFF);
28 41
29 // The rightmost byte of r_info is the type... 42 // The other 3 bytes of r_info are the symbol.
30 elf32_rel_386_type_values type =
31 (elf32_rel_386_type_values)(unsigned char)rel.r_info;
32
33 // The other 3 bytes of r_info are the symbol
34 uint32_t symbol = rel.r_info >> 8; 43 uint32_t symbol = rel.r_info >> 8;
35 44
36 switch(type) 45 switch (type) {
37 {
38 case R_386_NONE: 46 case R_386_NONE:
39 case R_386_32: 47 case R_386_32:
40 case R_386_PC32: 48 case R_386_PC32:
41 case R_386_GOT32: 49 case R_386_GOT32:
42 case R_386_PLT32: 50 case R_386_PLT32:
43 case R_386_COPY: 51 case R_386_COPY:
44 case R_386_GLOB_DAT: 52 case R_386_GLOB_DAT:
45 case R_386_JMP_SLOT: 53 case R_386_JMP_SLOT:
46 return false; 54 return false;
47 55
48 case R_386_RELATIVE: 56 case R_386_RELATIVE:
49 if (symbol != 0) 57 if (symbol != 0)
50 return false; 58 return false;
51 59
52 // This is a basic ABS32 relocation address 60 // This is a basic ABS32 relocation address.
53 *result = rel.r_offset; 61 *result = rel.r_offset;
54 return true; 62 return true;
55 63
56 case R_386_GOTOFF: 64 case R_386_GOTOFF:
57 case R_386_GOTPC: 65 case R_386_GOTPC:
58 case R_386_TLS_TPOFF: 66 case R_386_TLS_TPOFF:
59 return false; 67 return false;
60 } 68 }
61 69
62 return false; 70 return false;
63 } 71 }
64 72
65 CheckBool DisassemblerElf32X86::ParseRelocationSection( 73 CheckBool DisassemblerElf32X86::ParseRelocationSection(
66 const Elf32_Shdr *section_header, 74 const Elf32_Shdr* section_header,
67 AssemblyProgram* program) { 75 AssemblyProgram* program) {
68 // We can reproduce the R_386_RELATIVE entries in one of the relocation 76 // We can reproduce the R_386_RELATIVE entries in one of the relocation table
69 // table based on other information in the patch, given these 77 // based on other information in the patch, given these conditions:
70 // conditions....
71 // 78 //
72 // All R_386_RELATIVE entries are: 79 // All R_386_RELATIVE entries are:
73 // 1) In the same relocation table 80 // 1) In the same relocation table
74 // 2) Are consecutive 81 // 2) Are consecutive
75 // 3) Are sorted in memory address order 82 // 3) Are sorted in memory address order
76 // 83 //
77 // Happily, this is normally the case, but it's not required by spec 84 // Happily, this is normally the case, but it's not required by spec, so we
78 // so we check, and just don't do it if we don't match up. 85 // check, and just don't do it if we don't match up.
79 86
80 // The expectation is that one relocation section will contain 87 // The expectation is that one relocation section will contain all of our
81 // all of our R_386_RELATIVE entries in the expected order followed 88 // R_386_RELATIVE entries in the expected order followed by assorted other
82 // by assorted other entries we can't use special handling for. 89 // entries we can't use special handling for.
83 90
84 bool match = true; 91 bool match = true;
85 92
86 // Walk all the bytes in the section, matching relocation table or not 93 // Walk all the bytes in the section, matching relocation table or not.
87 size_t file_offset = section_header->sh_offset; 94 FileOffset file_offset = section_header->sh_offset;
88 size_t section_end = section_header->sh_offset + section_header->sh_size; 95 FileOffset section_end = file_offset + section_header->sh_size;
89 96
90 Elf32_Rel *section_relocs_iter = 97 const Elf32_Rel* section_relocs_iter = reinterpret_cast<const Elf32_Rel*>(
91 (Elf32_Rel *)OffsetToPointer(section_header->sh_offset); 98 FileOffsetToPointer(section_header->sh_offset));
92 99
93 uint32_t section_relocs_count = 100 uint32_t section_relocs_count =
94 section_header->sh_size / section_header->sh_entsize; 101 section_header->sh_size / section_header->sh_entsize;
95 102
96 if (abs32_locations_.empty()) 103 if (abs32_locations_.empty())
97 match = false; 104 match = false;
98 105
99 if (abs32_locations_.size() > section_relocs_count) 106 if (abs32_locations_.size() > section_relocs_count)
100 match = false; 107 match = false;
101 108
102 std::vector<RVA>::iterator reloc_iter = abs32_locations_.begin(); 109 std::vector<RVA>::iterator reloc_iter = abs32_locations_.begin();
103 110
104 while (match && (reloc_iter != abs32_locations_.end())) { 111 while (match && (reloc_iter != abs32_locations_.end())) {
105 if (section_relocs_iter->r_info != R_386_RELATIVE || 112 if (section_relocs_iter->r_info != R_386_RELATIVE ||
106 section_relocs_iter->r_offset != *reloc_iter) 113 section_relocs_iter->r_offset != *reloc_iter) {
107 match = false; 114 match = false;
108 section_relocs_iter++; 115 }
109 reloc_iter++; 116 ++section_relocs_iter;
117 ++reloc_iter;
110 } 118 }
111 119
112 if (match) { 120 if (match) {
113 // Skip over relocation tables 121 // Skip over relocation tables.
114 if (!program->EmitElfRelocationInstruction()) 122 if (!program->EmitElfRelocationInstruction())
115 return false; 123 return false;
116 file_offset += sizeof(Elf32_Rel) * abs32_locations_.size(); 124 file_offset += sizeof(Elf32_Rel) * abs32_locations_.size();
117 } 125 }
118 126
119 return ParseSimpleRegion(file_offset, section_end, program); 127 return ParseSimpleRegion(file_offset, section_end, program);
120 } 128 }
121 129
130 // TODO(huangs): Detect and avoid overlap with abs32 addresses.
122 CheckBool DisassemblerElf32X86::ParseRel32RelocsFromSection( 131 CheckBool DisassemblerElf32X86::ParseRel32RelocsFromSection(
123 const Elf32_Shdr* section_header) { 132 const Elf32_Shdr* section_header) {
124 uint32_t start_file_offset = section_header->sh_offset; 133 FileOffset start_file_offset = section_header->sh_offset;
125 uint32_t end_file_offset = start_file_offset + section_header->sh_size; 134 FileOffset end_file_offset = start_file_offset + section_header->sh_size;
126 135
127 const uint8_t* start_pointer = OffsetToPointer(start_file_offset); 136 const uint8_t* start_pointer = FileOffsetToPointer(start_file_offset);
128 const uint8_t* end_pointer = OffsetToPointer(end_file_offset); 137 const uint8_t* end_pointer = FileOffsetToPointer(end_file_offset);
129 138
130 // Quick way to convert from Pointer to RVA within a single Section is to 139 // Quick way to convert from Pointer to RVA within a single Section is to
131 // subtract 'pointer_to_rva'. 140 // subtract |pointer_to_rva|.
132 const uint8_t* const adjust_pointer_to_rva = 141 const uint8_t* const adjust_pointer_to_rva =
133 start_pointer - section_header->sh_addr; 142 start_pointer - section_header->sh_addr;
134 143
135 // Find the rel32 relocations. 144 // Find the rel32 relocations.
136 const uint8_t* p = start_pointer; 145 const uint8_t* p = start_pointer;
137 while (p < end_pointer) { 146 while (p < end_pointer) {
138 //RVA current_rva = static_cast<RVA>(p - adjust_pointer_to_rva);
139
140 // Heuristic discovery of rel32 locations in instruction stream: are the 147 // Heuristic discovery of rel32 locations in instruction stream: are the
141 // next few bytes the start of an instruction containing a rel32 148 // next few bytes the start of an instruction containing a rel32
142 // addressing mode? 149 // addressing mode?
143 const uint8_t* rel32 = NULL; 150 const uint8_t* rel32 = nullptr;
144 151
145 if (p + 5 <= end_pointer) { 152 if (p + 5 <= end_pointer) {
146 if (*p == 0xE8 || *p == 0xE9) { // jmp rel32 and call rel32 153 if (*p == 0xE8 || *p == 0xE9) { // jmp rel32 and call rel32
147 rel32 = p + 1; 154 rel32 = p + 1;
148 } 155 }
149 } 156 }
150 if (p + 6 <= end_pointer) { 157 if (p + 6 <= end_pointer) {
151 if (*p == 0x0F && (*(p+1) & 0xF0) == 0x80) { // Jcc long form 158 if (*p == 0x0F && (p[1] & 0xF0) == 0x80) { // Jcc long form
152 if (p[1] != 0x8A && p[1] != 0x8B) // JPE/JPO unlikely 159 if (p[1] != 0x8A && p[1] != 0x8B) // JPE/JPO unlikely
153 rel32 = p + 2; 160 rel32 = p + 2;
154 } 161 }
155 } 162 }
156 if (rel32) { 163 if (rel32) {
157 RVA rva = static_cast<RVA>(rel32 - adjust_pointer_to_rva); 164 RVA rva = static_cast<RVA>(rel32 - adjust_pointer_to_rva);
158 TypedRVAX86* rel32_rva = new TypedRVAX86(rva); 165 scoped_ptr<TypedRVAX86> rel32_rva(new TypedRVAX86(rva));
159 166
160 if (!rel32_rva->ComputeRelativeTarget(rel32)) { 167 if (!rel32_rva->ComputeRelativeTarget(rel32))
161 delete rel32_rva;
162 return false; 168 return false;
163 }
164 169
165 RVA target_rva = rel32_rva->rva() + rel32_rva->relative_target(); 170 RVA target_rva = rel32_rva->rva() + rel32_rva->relative_target();
166 // To be valid, rel32 target must be within image, and within this 171 if (IsValidTargetRVA(target_rva)) {
167 // section. 172 rel32_locations_.push_back(rel32_rva.release());
168 if (IsValidRVA(target_rva)) {
169 rel32_locations_.push_back(rel32_rva);
170 #if COURGETTE_HISTOGRAM_TARGETS 173 #if COURGETTE_HISTOGRAM_TARGETS
171 ++rel32_target_rvas_[target_rva]; 174 ++rel32_target_rvas_[target_rva];
172 #endif 175 #endif
173 p = rel32 + 4; 176 p = rel32 + 4;
174 continue; 177 continue;
175 } else {
176 delete rel32_rva;
177 } 178 }
178 } 179 }
179 p += 1; 180 p += 1;
180 } 181 }
181 182
182 return true; 183 return true;
183 } 184 }
184 185
185 } // namespace courgette 186 } // namespace courgette
OLDNEW
« no previous file with comments | « courgette/disassembler_elf_32_x86.h ('k') | courgette/disassembler_elf_32_x86_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698