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