1 : // Copyright 2013 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : // The COFF image layout builder does a lot of things (maybe too much for
16 : // its own good):
17 : // - Assign an address to each block.
18 : // - Create and add a relocation block for each section, and remove old ones.
19 : // - Fix file offset pointers in section contents, headers, and tables.
20 : //
21 : // Since these tasks are very dependent on internals of COFF, which are
22 : // missing from our intermediate representation (the block graph and
23 : // associated metadata), they must rely on additional data structures and
24 : // book-keeping. Hence they are all collected in this single step instead
25 : // of existing as distinct transforms.
26 : //
27 : // New relocation blocks need to be bound to specific sections, and that
28 : // link is not represented in the section info we have in the block
29 : // graph. It is probably not useful there as it would only be needed during
30 : // patching of COFF headers, and useless with PE.
31 : //
32 : // Old relocation block removal could be done in a separate transform, but
33 : // is image-layout-dependent and hence does not classify as a block graph
34 : // transform.
35 : //
36 : // Fixing references could alternatively be done in the file writer. Most
37 : // header fields need to be patched (or their reference updated) during
38 : // image laying out, though. Also, relocation references need to be handled
39 : // with the creation of the new relocation tables (and do not require
40 : // patching). Here we choose to handle all references in the image layout
41 : // builder instead of spreading the task across classes.
42 :
43 : #include "syzygy/pe/coff_image_layout_builder.h"
44 :
45 : #include <vector>
46 :
47 : #include "base/auto_reset.h"
48 : #include "base/strings/string_util.h"
49 : #include "syzygy/block_graph/typed_block.h"
50 : #include "syzygy/common/align.h"
51 : #include "syzygy/pe/coff_utils.h"
52 : #include "syzygy/pe/pe_utils.h"
53 :
54 : namespace pe {
55 : namespace {
56 :
57 : using block_graph::BlockGraph;
58 : using block_graph::ConstTypedBlock;
59 : using block_graph::OrderedBlockGraph;
60 : using block_graph::TypedBlock;
61 : using core::FileOffsetAddress;
62 :
63 : // A temporary vector holding relocation entries, while building new
64 : // relocation blocks.
65 : typedef std::vector<IMAGE_RELOCATION> RelocVector;
66 :
67 : // A map from references to symbol indexes, in order to translate references
68 : // to relocations, which are symbol-based.
69 : typedef std::map<std::pair<BlockGraph::Block*, BlockGraph::Offset>, size_t>
70 : SymbolMap;
71 :
72 : // A map from section IDs to their (new) position in the resulting layout.
73 : typedef std::map<BlockGraph::SectionId, size_t> SectionIndexMap;
74 :
75 : // Microsoft specifications recommend 4-byte alignment for object files.
76 : const size_t kFileAlignment = 4;
77 :
78 : // The name of the new relocation blocks, generated from references.
79 : const char kNewRelocsBlockName[] = "<refs>";
80 :
81 : // Retrieve the COFF relocation type corresponding to the specified
82 : // reference type and size.
83 : //
84 : // @param ref_type the reference type.
85 : // @param ref_size the reference size.
86 : // @param coff_reloc_type where to put the resulting COFF relocation type.
87 : // @returns true on success, false on failure.
88 : bool GetCoffRelocationType(BlockGraph::ReferenceType ref_type,
89 : BlockGraph::Size ref_size,
90 E : uint16* coff_reloc_type) {
91 E : switch (ref_type) {
92 : case BlockGraph::RELOC_ABSOLUTE_REF:
93 E : DCHECK_EQ(sizeof(uint32), ref_size);
94 E : *coff_reloc_type = IMAGE_REL_I386_DIR32;
95 E : return true;
96 : case BlockGraph::RELOC_RELATIVE_REF:
97 E : DCHECK_EQ(sizeof(uint32), ref_size);
98 E : *coff_reloc_type = IMAGE_REL_I386_DIR32NB;
99 E : return true;
100 : case BlockGraph::RELOC_SECTION_REF:
101 E : DCHECK_EQ(sizeof(uint16), ref_size);
102 E : *coff_reloc_type = IMAGE_REL_I386_SECTION;
103 E : return true;
104 : case BlockGraph::RELOC_SECTION_OFFSET_REF:
105 E : if (ref_size == sizeof(uint32)) {
106 E : *coff_reloc_type = IMAGE_REL_I386_SECREL;
107 E : } else {
108 i : DCHECK_EQ(1u, ref_size);
109 i : *coff_reloc_type = IMAGE_REL_I386_SECREL7;
110 : }
111 E : return true;
112 : case BlockGraph::RELOC_PC_RELATIVE_REF:
113 E : DCHECK_EQ(sizeof(uint32), ref_size);
114 E : *coff_reloc_type = IMAGE_REL_I386_REL32;
115 E : return true;
116 : default:
117 i : LOG(ERROR) << "Unexpected reference type.";
118 i : return false;
119 : }
120 E : }
121 :
122 : // Write a reference value at the specified location. Write the full value
123 : // for non-relocation references, or the additional offset only for
124 : // relocation references.
125 : //
126 : // @tparam ValueType the type of data to write.
127 : // @param ref the reference to write.
128 : // @param block_offset the offset within @p block to alter.
129 : // @param block the block to alter.
130 : template <typename ValueType>
131 : bool WriteReferenceValue(BlockGraph::Reference ref,
132 : BlockGraph::Offset block_offset,
133 E : BlockGraph::Block* block) {
134 E : DCHECK_EQ(sizeof(ValueType), ref.size());
135 E : TypedBlock<ValueType> value;
136 E : if (!value.Init(block_offset, block)) {
137 i : LOG(ERROR) << "Unable to cast reference.";
138 i : return false;
139 : }
140 E : if ((ref.type() & BlockGraph::RELOC_REF_BIT) != 0) {
141 E : *value = ref.offset() - ref.base();
142 E : } else {
143 E : *value = ref.offset();
144 : }
145 E : return true;
146 E : }
147 :
148 : // For each relocation reference in @p block, add a COFF relocation to the
149 : // specified vector.
150 : //
151 : // @param block the block whose references are to be translated to
152 : // relocations.
153 : // @param symbol_map the symbol map to use to match references with symbols.
154 : // @param relocs vector to which the relocations are to be added.
155 : // @returns true on success, false on failure.
156 : bool AddRelocs(const BlockGraph::Block& block,
157 : const SymbolMap& symbol_map,
158 E : RelocVector* relocs) {
159 E : DCHECK(relocs != NULL);
160 :
161 : BlockGraph::Block::ReferenceMap::const_iterator it =
162 E : block.references().begin();
163 E : for (; it != block.references().end(); ++it) {
164 : // Skip non-relocation references.
165 E : if ((it->second.type() & BlockGraph::RELOC_REF_BIT) == 0)
166 E : continue;
167 :
168 E : IMAGE_RELOCATION reloc = {};
169 :
170 : // Sections constructed by this class all have zero base RVA, so the
171 : // virtual address is just the offset.
172 E : reloc.VirtualAddress = it->first;
173 :
174 : SymbolMap::const_iterator symbol_it =
175 : symbol_map.find(std::make_pair(it->second.referenced(),
176 E : it->second.base()));
177 E : if (symbol_it == symbol_map.end()) {
178 i : LOG(ERROR) << "Missing COFF symbol for reference within a section block; "
179 : << "cannot translate to relocation.";
180 i : return false;
181 : }
182 E : reloc.SymbolTableIndex = symbol_it->second;
183 : if (!GetCoffRelocationType(it->second.type(), it->second.size(),
184 E : &reloc.Type))
185 i : return false;
186 :
187 E : relocs->push_back(reloc);
188 E : }
189 E : return true;
190 E : }
191 :
192 : } // namespace
193 :
194 : CoffImageLayoutBuilder::CoffImageLayoutBuilder(ImageLayout* image_layout)
195 : : PECoffImageLayoutBuilder(image_layout),
196 : headers_block_(NULL),
197 : symbols_block_(NULL),
198 E : strings_block_(NULL) {
199 E : PECoffImageLayoutBuilder::Init(kFileAlignment, kFileAlignment);
200 E : }
201 :
202 : bool CoffImageLayoutBuilder::LayoutImage(
203 E : const OrderedBlockGraph& ordered_graph) {
204 E : DCHECK_EQ(image_layout_->blocks.graph(), ordered_graph.block_graph());
205 :
206 E : BlockGraph::Block* headers_block = NULL;
207 E : BlockGraph::Block* symbols_block = NULL;
208 E : BlockGraph::Block* strings_block = NULL;
209 :
210 : if (!FindCoffSpecialBlocks(image_layout_->blocks.graph(),
211 E : &headers_block, &symbols_block, &strings_block)) {
212 i : LOG(ERROR) << "Block graph is missing some COFF special blocks. "
213 : << "Not a COFF block graph?";
214 i : return false;
215 : }
216 E : DCHECK(headers_block != NULL);
217 E : DCHECK(symbols_block != NULL);
218 E : DCHECK(strings_block != NULL);
219 :
220 E : DCHECK(headers_block_ == NULL);
221 E : DCHECK(symbols_block_ == NULL);
222 E : DCHECK(strings_block_ == NULL);
223 : base::AutoReset<BlockGraph::Block*> auto_reset_headers_block(
224 E : &headers_block_, headers_block);
225 : base::AutoReset<BlockGraph::Block*> auto_reset_symbols_block(
226 E : &symbols_block_, symbols_block);
227 : base::AutoReset<BlockGraph::Block*> auto_reset_strings_block(
228 E : &strings_block_, strings_block);
229 :
230 E : if (!LayoutHeaders())
231 i : return false;
232 :
233 E : if (!LayoutSectionBlocks(ordered_graph))
234 i : return false;
235 :
236 E : if (!LayoutSymbolAndStringTables(ordered_graph))
237 i : return false;
238 :
239 E : if (!RemoveOldRelocBlocks())
240 i : return false;
241 :
242 E : return true;
243 E : }
244 :
245 E : bool CoffImageLayoutBuilder::LayoutHeaders() {
246 E : DCHECK(headers_block_ != NULL);
247 E : DCHECK_EQ(0u, image_layout_->blocks.address_space_impl().size());
248 E : DCHECK_EQ(0u, image_layout_->sections.size());
249 :
250 E : if (IsValidDosHeaderBlock(headers_block_)) {
251 i : LOG(ERROR) << "Found DOS header in purported COFF file.";
252 i : return false;
253 : }
254 :
255 : // Lay out headers as the block in the image layout.
256 E : DCHECK_EQ(0u, cursor_.value());
257 E : if (!LayoutBlockImpl(headers_block_))
258 i : return false;
259 :
260 E : return true;
261 E : }
262 :
263 : bool CoffImageLayoutBuilder::LayoutSectionBlocks(
264 E : const OrderedBlockGraph& ordered_graph) {
265 E : DCHECK(headers_block_ != NULL);
266 E : DCHECK(symbols_block_ != NULL);
267 E : DCHECK_LT(0u, cursor_.value());
268 E : DCHECK_EQ(0u, image_layout_->sections.size());
269 :
270 : // Fetch pointers to headers.
271 E : ConstTypedBlock<IMAGE_FILE_HEADER> file_header;
272 E : if (!file_header.Init(0, headers_block_)) {
273 i : LOG(ERROR) << "Unable to cast file header.";
274 i : return false;
275 : }
276 E : TypedBlock<IMAGE_SECTION_HEADER> section_headers;
277 E : if (!section_headers.Init(sizeof(IMAGE_FILE_HEADER), headers_block_)) {
278 i : LOG(ERROR) << "Unable to cast section headers.";
279 i : return false;
280 : }
281 E : if (file_header->NumberOfSections != section_headers.ElementCount()) {
282 i : LOG(ERROR) << "File header section count does not agree with "
283 : << "element count in headers block ("
284 : << file_header->NumberOfSections
285 : << " vs " << section_headers.ElementCount() << ").";
286 i : return false;
287 : }
288 :
289 : // Fetch pointer to symbols.
290 E : ConstTypedBlock<IMAGE_SYMBOL> symbols;
291 E : if (!symbols.Init(0, symbols_block_)) {
292 i : LOG(ERROR) << "Unable to cast symbol table.";
293 i : return false;
294 : }
295 E : size_t num_symbols = symbols.ElementCount();
296 :
297 : // Collect symbol information for relocations.
298 E : SymbolMap symbol_map;
299 : BlockGraph::Block::ReferenceMap::const_iterator it =
300 E : symbols_block_->references().begin();
301 E : for (size_t i = 0; i < num_symbols; i += 1 + symbols[i].NumberOfAuxSymbols) {
302 E : if (it != symbols_block_->references().end()) {
303 E : size_t ref_symbol_index = it->first / sizeof(IMAGE_SYMBOL);
304 E : DCHECK_LE(i, ref_symbol_index);
305 E : DCHECK_GT(num_symbols, ref_symbol_index);
306 :
307 E : if (i == ref_symbol_index) {
308 : // Resolved (referenced) symbol. We override previously inserted
309 : // symbols for the same reference; this gives priority to actual
310 : // symbols at offset zero, rather than section definition symbols.
311 E : DCHECK_LT(0, symbols[i].SectionNumber);
312 : std::pair<BlockGraph::Block*, BlockGraph::Offset> ref_pair =
313 E : std::make_pair(it->second.referenced(), it->second.base());
314 E : symbol_map.insert(std::make_pair(ref_pair, i)).first->second = i;
315 :
316 : // Skip any other references for this symbol or its auxiliary
317 : // symbols.
318 E : size_t next_index = i + 1 + symbols[i].NumberOfAuxSymbols;
319 : do {
320 E : ++it;
321 : } while (it != symbols_block_->references().end() &&
322 E : it->first / sizeof(IMAGE_SYMBOL) < next_index);
323 :
324 E : continue;
325 : }
326 : }
327 :
328 : // External or misc (unreferenced), that lies between references.
329 E : DCHECK_GE(0, symbols[i].SectionNumber);
330 : std::pair<BlockGraph::Block*, BlockGraph::Offset> ref_pair =
331 E : std::make_pair(symbols_block_, i * sizeof(symbols[i]));
332 E : symbol_map.insert(std::make_pair(ref_pair, i));
333 E : }
334 E : DCHECK(it == symbols_block_->references().end());
335 :
336 : // Lay out section and relocation blocks.
337 : OrderedBlockGraph::SectionList::const_iterator section_it =
338 E : ordered_graph.ordered_sections().begin();
339 : OrderedBlockGraph::SectionList::const_iterator section_end =
340 E : ordered_graph.ordered_sections().end();
341 E : size_t section_index = 0;
342 E : for (; section_it != section_end; ++section_it) {
343 E : BlockGraph::Section* section = (*section_it)->section();
344 E : DCHECK(section != NULL);
345 :
346 : // Fill in common section header information.
347 E : if (section_index >= file_header->NumberOfSections) {
348 i : LOG(ERROR) << "Not enough space in headers block for "
349 : << "so many sections (" << section_index << ").";
350 i : return false;
351 : }
352 E : IMAGE_SECTION_HEADER* header = §ion_headers[section_index];
353 :
354 E : std::memset(header, 0, sizeof(*header));
355 : std::strncpy(reinterpret_cast<char*>(header->Name),
356 : section->name().c_str(),
357 E : arraysize(header->Name));
358 E : header->Characteristics = section->characteristics();
359 :
360 : // Handle section data.
361 E : if (!OpenSection(*section))
362 i : return false;
363 :
364 E : FileOffsetAddress section_start(cursor_.value());
365 E : RelocVector relocs;
366 :
367 : // Lay out section blocks and collect relocations.
368 : OrderedBlockGraph::BlockList::const_iterator block_it =
369 E : (*section_it)->ordered_blocks().begin();
370 : OrderedBlockGraph::BlockList::const_iterator block_end =
371 E : (*section_it)->ordered_blocks().end();
372 E : for (; block_it != block_end; ++block_it) {
373 E : BlockGraph::Block* block = *block_it;
374 E : DCHECK(block != NULL);
375 : DCHECK(block->type() == BlockGraph::CODE_BLOCK ||
376 : (block->attributes() &
377 E : (BlockGraph::SECTION_CONTRIB | BlockGraph::COFF_BSS)) != 0);
378 :
379 : // Fix references.
380 : BlockGraph::Block::ReferenceMap::const_iterator ref_it =
381 E : block->references().begin();
382 E : for (; ref_it != block->references().end(); ++ref_it) {
383 : // Section blocks should only have relocations and function-relative
384 : // file pointers, represented as section offsets, thanks to
385 : // function-level linking.
386 E : BlockGraph::Reference ref(ref_it->second);
387 : if ((ref.type() & BlockGraph::RELOC_REF_BIT) == 0 &&
388 E : ref.type() != BlockGraph::SECTION_OFFSET_REF) {
389 i : LOG(ERROR) << "Unexpected reference type " << ref.type()
390 : << " in section " << section_index << ".";
391 i : return false;
392 : }
393 :
394 E : switch (ref.size()) {
395 : case sizeof(uint32):
396 E : if (!WriteReferenceValue<uint32>(ref, ref_it->first, block))
397 i : return false;
398 E : break;
399 : case sizeof(uint16):
400 E : if (!WriteReferenceValue<uint16>(ref, ref_it->first, block))
401 i : return false;
402 E : break;
403 : case sizeof(uint8):
404 : // TODO(chrisha): This is really a special 7-bit relocation; we do
405 : // not touch these, for now.
406 i : break;
407 : default:
408 i : LOG(ERROR) << "Unsupported relocation value size ("
409 : << ref.size() << ").";
410 i : return false;
411 : }
412 E : }
413 :
414 : // Lay out and collect relocations.
415 E : if (!LayoutBlock(block))
416 i : return false;
417 E : if (!AddRelocs(*block, symbol_map, &relocs))
418 i : return false;
419 E : }
420 :
421 E : if (!CloseSection())
422 i : return false;
423 :
424 : // Fix section header. We use section_index - 1, as the value has been
425 : // incremented already.
426 : const ImageLayout::SectionInfo& info =
427 E : image_layout_->sections[section_index];
428 E : if ((section->characteristics() & IMAGE_SCN_CNT_UNINITIALIZED_DATA) == 0) {
429 : // Normal section.
430 E : header->PointerToRawData = section_start.value();
431 E : header->SizeOfRawData = info.data_size;
432 E : } else {
433 : // BSS section. The COFF specifications state that SizeOfRawData
434 : // should be set to zero, but MSVC sets it to the size of the
435 : // uninitialized data.
436 E : header->SizeOfRawData = info.size;
437 : }
438 E : DCHECK_EQ(header->Characteristics, info.characteristics);
439 :
440 : // Lay out relocations, if necessary.
441 E : if (relocs.size() != 0) {
442 E : size_t relocs_size = relocs.size() * sizeof(relocs[0]);
443 : BlockGraph::Block* relocs_block =
444 : image_layout_->blocks.graph()->AddBlock(BlockGraph::DATA_BLOCK,
445 : relocs_size,
446 E : kNewRelocsBlockName);
447 E : DCHECK(relocs_block != NULL);
448 E : relocs_block->set_attribute(BlockGraph::COFF_RELOC_DATA);
449 E : if (relocs_block->CopyData(relocs_size, &relocs[0]) == NULL)
450 i : return false;
451 :
452 : // Fix relocation information in header.
453 E : header->PointerToRelocations = cursor_.value();
454 E : header->NumberOfRelocations = relocs.size();
455 :
456 : // Lay out the relocation block outside of the section.
457 E : if (!LayoutBlockImpl(relocs_block))
458 i : return false;
459 : }
460 :
461 E : ++section_index;
462 E : }
463 :
464 E : if (section_index < file_header->NumberOfSections) {
465 i : LOG(ERROR) << "Missing sections from ordered block graph ("
466 : << file_header->NumberOfSections << " expected vs "
467 : << section_index << " found).";
468 i : return false;
469 : }
470 :
471 E : return true;
472 E : }
473 :
474 : bool CoffImageLayoutBuilder::LayoutSymbolAndStringTables(
475 E : const OrderedBlockGraph& ordered_graph) {
476 E : DCHECK(headers_block_ != NULL);
477 E : DCHECK(symbols_block_ != NULL);
478 E : DCHECK(strings_block_ != NULL);
479 :
480 E : TypedBlock<IMAGE_FILE_HEADER> file_header;
481 E : if (!file_header.Init(0, headers_block_)) {
482 i : LOG(ERROR) << "Unable to cast file header.";
483 i : return false;
484 : }
485 :
486 E : TypedBlock<IMAGE_SYMBOL> symbols;
487 E : if (!symbols.Init(0, symbols_block_)) {
488 i : LOG(ERROR) << "Unable to cast symbol table.";
489 i : return false;
490 : }
491 :
492 E : file_header->PointerToSymbolTable = cursor_.value();
493 E : file_header->NumberOfSymbols = symbols.ElementCount();
494 :
495 : // Lay out the blocks.
496 E : if (!LayoutBlockImpl(symbols_block_))
497 i : return false;
498 E : if (!LayoutBlockImpl(strings_block_))
499 i : return false;
500 :
501 : // Compute the section index map, used to remap symbol section references.
502 E : SectionIndexMap section_index_map;
503 : OrderedBlockGraph::SectionList::const_iterator section_it =
504 E : ordered_graph.ordered_sections().begin();
505 : OrderedBlockGraph::SectionList::const_iterator section_end =
506 E : ordered_graph.ordered_sections().end();
507 E : size_t section_index = 0;
508 E : for (; section_it != section_end; ++section_it) {
509 E : BlockGraph::Section* section = (*section_it)->section();
510 E : DCHECK(section != NULL);
511 E : section_index_map.insert(std::make_pair(section->id(), section_index));
512 E : ++section_index;
513 E : }
514 :
515 : // Fix references.
516 : BlockGraph::Block::ReferenceMap::const_iterator it =
517 E : symbols_block_->references().begin();
518 E : for (; it != symbols_block_->references().end(); ++it) {
519 E : size_t symbol_index = it->first / sizeof(IMAGE_SYMBOL);
520 E : DCHECK_GT(file_header->NumberOfSymbols, symbol_index);
521 :
522 E : switch (it->second.type()) {
523 : case BlockGraph::SECTION_REF: {
524 E : DCHECK_EQ(2u, it->second.size());
525 E : TypedBlock<uint16> section_number;
526 E : if (!section_number.Init(it->first, symbols_block_)) {
527 i : LOG(ERROR) << "Unable to cast reference.";
528 i : return false;
529 : }
530 :
531 : SectionIndexMap::iterator section_index_it =
532 E : section_index_map.find(it->second.referenced()->section());
533 E : if (section_index_it == section_index_map.end()) {
534 i : LOG(ERROR) << "Reference to unmapped section.";
535 i : return false;
536 : }
537 E : *section_number = section_index_it->second + 1;
538 E : DCHECK_EQ(*section_number, symbols[symbol_index].SectionNumber);
539 E : break;
540 : }
541 :
542 : case BlockGraph::SECTION_OFFSET_REF: {
543 E : DCHECK_EQ(4u, it->second.size());
544 E : TypedBlock<uint32> value;
545 E : if (!value.Init(it->first, symbols_block_)) {
546 i : LOG(ERROR) << "Unable to cast reference.";
547 i : return false;
548 : }
549 :
550 E : *value = it->second.offset();
551 : DCHECK_EQ(static_cast<size_t>(it->second.offset()),
552 E : symbols[symbol_index].Value);
553 E : break;
554 : }
555 :
556 : default:
557 i : LOG(ERROR) << "Unexpected reference type " << it->second.type()
558 : << " in symbol table.";
559 i : return false;
560 : }
561 E : }
562 :
563 E : return true;
564 E : }
565 :
566 E : bool CoffImageLayoutBuilder::RemoveOldRelocBlocks() {
567 : // Find blocks not mapped in the image layout, and ensure they are (old)
568 : // COFF relocation blocks; if not, that is an error.
569 : //
570 : // Relocation blocks found during this pass do not include new relocation
571 : // blocks (which must have been inserted into the image layout).
572 : BlockGraph::BlockMap& blocks =
573 E : image_layout_->blocks.graph()->blocks_mutable();
574 E : std::vector<BlockGraph::Block*> blocks_to_remove;
575 :
576 E : BlockGraph::BlockMap::iterator it = blocks.begin();
577 E : for (; it != blocks.end(); ++it) {
578 E : if (!image_layout_->blocks.ContainsBlock(&it->second)) {
579 E : if ((it->second.attributes() & BlockGraph::COFF_RELOC_DATA) == 0) {
580 i : LOG(ERROR) << "Found unmapped block \"" << it->second.name()
581 : << "\" in block graph; "
582 : << "originally mapped at address " << it->second.addr()
583 : << ".";
584 i : return false;
585 : }
586 E : blocks_to_remove.push_back(&it->second);
587 : }
588 E : }
589 :
590 : // Remove old relocation blocks from the block graph.
591 : std::vector<BlockGraph::Block*>::iterator it_to_remove =
592 E : blocks_to_remove.begin();
593 E : for (; it_to_remove != blocks_to_remove.end(); ++it_to_remove) {
594 E : if (!image_layout_->blocks.graph()->RemoveBlock(*it_to_remove)) {
595 i : LOG(ERROR) << "Unable to remove block with ID " << (*it_to_remove)->id()
596 : << " from the block graph.";
597 : }
598 E : }
599 :
600 : DCHECK_EQ(image_layout_->blocks.size(),
601 E : image_layout_->blocks.graph()->blocks().size());
602 :
603 E : return true;
604 E : }
605 :
606 : } // namespace pe
|