135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// Copyright (c) 2010 Google Inc.
235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// All rights reserved.
335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek//
435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// Redistribution and use in source and binary forms, with or without
535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// modification, are permitted provided that the following conditions are
635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// met:
735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek//
835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek//     * Redistributions of source code must retain the above copyright
935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// notice, this list of conditions and the following disclaimer.
1035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek//     * Redistributions in binary form must reproduce the above
1135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// copyright notice, this list of conditions and the following disclaimer
1235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// in the documentation and/or other materials provided with the
1335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// distribution.
1435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek//     * Neither the name of Google Inc. nor the names of its
1535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// contributors may be used to endorse or promote products derived from
1635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// this software without specific prior written permission.
1735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek//
1835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
3035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
3135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
3235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// macho_reader_unittest.cc: Unit tests for google_breakpad::Mach_O::FatReader
3335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// and google_breakpad::Mach_O::Reader.
3435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
3535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek#include <map>
3635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek#include <string>
3735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek#include <vector>
3835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
3935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek#include "breakpad_googletest_includes.h"
4035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek#include "common/mac/macho_reader.h"
4135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek#include "common/test_assembler.h"
4235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
4335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczareknamespace mach_o = google_breakpad::mach_o;
4435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczareknamespace test_assembler = google_breakpad::test_assembler;
4535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
4635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekusing mach_o::FatReader;
4735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekusing mach_o::FileFlags;
4835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekusing mach_o::FileType;
4935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekusing mach_o::LoadCommandType;
5035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekusing mach_o::Reader;
5135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekusing mach_o::Section;
5235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekusing mach_o::SectionMap;
5335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekusing mach_o::Segment;
5435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekusing test_assembler::Endianness;
5535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekusing test_assembler::Label;
5635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekusing test_assembler::kBigEndian;
5735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekusing test_assembler::kLittleEndian;
5835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekusing test_assembler::kUnsetEndian;
5935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekusing google_breakpad::ByteBuffer;
6035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekusing std::map;
6135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekusing std::string;
6235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekusing std::vector;
6335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekusing testing::AllOf;
6435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekusing testing::DoAll;
6535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekusing testing::Field;
6635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekusing testing::InSequence;
6735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekusing testing::Matcher;
6835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekusing testing::Return;
6935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekusing testing::SaveArg;
7035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekusing testing::Test;
7135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekusing testing::_;
7235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
7335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
7435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// Mock classes for the reader's various reporters and handlers.
7535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
7635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekclass MockFatReaderReporter: public FatReader::Reporter {
7735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek public:
7835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MockFatReaderReporter(const string &filename)
7935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      : FatReader::Reporter(filename) { }
8035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MOCK_METHOD0(BadHeader, void());
8135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MOCK_METHOD0(MisplacedObjectFile, void());
8235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MOCK_METHOD0(TooShort, void());
8335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek};
8435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
8535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekclass MockReaderReporter: public Reader::Reporter {
8635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek public:
8735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MockReaderReporter(const string &filename) : Reader::Reporter(filename) { }
8835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MOCK_METHOD0(BadHeader, void());
8935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MOCK_METHOD4(CPUTypeMismatch, void(cpu_type_t cpu_type,
9035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                                     cpu_subtype_t cpu_subtype,
9135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                                     cpu_type_t expected_cpu_type,
9235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                                     cpu_subtype_t expected_cpu_subtype));
9335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MOCK_METHOD0(HeaderTruncated, void());
9435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MOCK_METHOD0(LoadCommandRegionTruncated, void());
9535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MOCK_METHOD3(LoadCommandsOverrun, void(size_t claimed, size_t i,
9635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                                         LoadCommandType type));
9735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MOCK_METHOD2(LoadCommandTooShort, void(size_t i, LoadCommandType type));
9835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MOCK_METHOD1(SectionsMissing, void(const string &name));
9935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MOCK_METHOD1(MisplacedSegmentData, void(const string &name));
10035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MOCK_METHOD2(MisplacedSectionData, void(const string &section,
10135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                                          const string &segment));
10235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MOCK_METHOD0(MisplacedSymbolTable, void());
10335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MOCK_METHOD1(UnsupportedCPUType, void(cpu_type_t cpu_type));
10435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek};
10535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
10635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekclass MockLoadCommandHandler: public Reader::LoadCommandHandler {
10735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek public:
10835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MOCK_METHOD2(UnknownCommand, bool(LoadCommandType, const ByteBuffer &));
10935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MOCK_METHOD1(SegmentCommand, bool(const Segment &));
11035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MOCK_METHOD2(SymtabCommand,  bool(const ByteBuffer &, const ByteBuffer &));
11135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek};
11235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
11335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekclass MockSectionHandler: public Reader::SectionHandler {
11435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek public:
11535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MOCK_METHOD1(HandleSection, bool(const Section &section));
11635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek};
11735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
11835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
11935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// Tests for mach_o::FatReader.
12035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
12135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// Since the effect of these functions is to write to stderr, the
12235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// results of these tests must be inspected by hand.
12335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST(FatReaderReporter, BadHeader) {
12435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  FatReader::Reporter reporter("filename");
12535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  reporter.BadHeader();
12635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
12735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
12835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST(FatReaderReporter, MisplacedObjectFile) {
12935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  FatReader::Reporter reporter("filename");
13035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  reporter.MisplacedObjectFile();
13135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
13235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
13335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST(FatReaderReporter, TooShort) {
13435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  FatReader::Reporter reporter("filename");
13535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  reporter.TooShort();
13635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
13735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
13835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST(MachOReaderReporter, BadHeader) {
13935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Reader::Reporter reporter("filename");
14035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  reporter.BadHeader();
14135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
14235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
14335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST(MachOReaderReporter, CPUTypeMismatch) {
14435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Reader::Reporter reporter("filename");
14535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  reporter.CPUTypeMismatch(CPU_TYPE_I386, CPU_SUBTYPE_X86_ALL,
14635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                           CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_ALL);
14735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
14835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
14935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST(MachOReaderReporter, HeaderTruncated) {
15035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Reader::Reporter reporter("filename");
15135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  reporter.HeaderTruncated();
15235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
15335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
15435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST(MachOReaderReporter, LoadCommandRegionTruncated) {
15535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Reader::Reporter reporter("filename");
15635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  reporter.LoadCommandRegionTruncated();
15735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
15835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
15935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST(MachOReaderReporter, LoadCommandsOverrun) {
16035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Reader::Reporter reporter("filename");
16135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  reporter.LoadCommandsOverrun(10, 9, LC_DYSYMTAB);
16235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  reporter.LoadCommandsOverrun(10, 9, 0);
16335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
16435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
16535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST(MachOReaderReporter, LoadCommandTooShort) {
16635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Reader::Reporter reporter("filename");
16735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  reporter.LoadCommandTooShort(11, LC_SYMTAB);
16835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
16935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
17035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST(MachOReaderReporter, SectionsMissing) {
17135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Reader::Reporter reporter("filename");
17235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  reporter.SectionsMissing("segment name");
17335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
17435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
17535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST(MachOReaderReporter, MisplacedSegmentData) {
17635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Reader::Reporter reporter("filename");
17735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  reporter.MisplacedSegmentData("segment name");
17835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
17935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
18035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST(MachOReaderReporter, MisplacedSectionData) {
18135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Reader::Reporter reporter("filename");
18235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  reporter.MisplacedSectionData("section name", "segment name");
18335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
18435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
18535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST(MachOReaderReporter, MisplacedSymbolTable) {
18635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Reader::Reporter reporter("filename");
18735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  reporter.MisplacedSymbolTable();
18835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
18935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
19035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST(MachOReaderReporter, UnsupportedCPUType) {
19135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Reader::Reporter reporter("filename");
19235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  reporter.UnsupportedCPUType(CPU_TYPE_HPPA);
19335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
19435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
19535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekstruct FatReaderFixture {
19635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  FatReaderFixture()
19735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      : fat(kBigEndian),
19835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek        reporter("reporter filename"),
19935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek        reader(&reporter), object_files(), object_files_size() {
20035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    EXPECT_CALL(reporter, BadHeader()).Times(0);
20135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    EXPECT_CALL(reporter, TooShort()).Times(0);
20235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
20335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    // here, start, and Mark are file offsets in 'fat'.
20435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    fat.start() = 0;
20535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  }
20635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Append a 'fat_arch' entry to 'fat', with the given field values.
20735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  void AppendFatArch(cpu_type_t type, cpu_subtype_t subtype,
20835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                     Label offset, Label size, uint32_t align) {
20935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    fat
21035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek        .B32(type)
21135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek        .B32(subtype)
21235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek        .B32(offset)
21335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek        .B32(size)
21435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek        .B32(align);
21535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  }
21635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Append |n| dummy 'fat_arch' entries to 'fat'. The cpu type and
21735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // subtype have unrealistic values.
21835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  void AppendDummyArchEntries(int n) {
21935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    for (int i = 0; i < n; i++)
22035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      AppendFatArch(0xb68ad617, 0x715a0840, 0, 0, 1);
22135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  }
22235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  void ReadFat(bool expect_parse_success = true) {
22335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    ASSERT_TRUE(fat.GetContents(&contents));
22435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    fat_bytes = reinterpret_cast<const uint8_t *>(contents.data());
22535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    if (expect_parse_success) {
22635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      EXPECT_TRUE(reader.Read(fat_bytes, contents.size()));
22735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      object_files = reader.object_files(&object_files_size);
22835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    }
22935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    else
23035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      EXPECT_FALSE(reader.Read(fat_bytes, contents.size()));
23135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  }
23235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  test_assembler::Section fat;
23335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MockFatReaderReporter reporter;
23435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  FatReader reader;
23535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  string contents;
23635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  const uint8_t *fat_bytes;
23735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  const struct fat_arch *object_files;
23835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  size_t object_files_size;
23935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek};
24035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
24135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekclass FatReaderTest: public FatReaderFixture, public Test { };
24235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
24335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(FatReaderTest, BadMagic) {
24435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_CALL(reporter, BadHeader()).Times(1);
24535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  fat
24635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .B32(0xcafed00d)           // magic number (incorrect)
24735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .B32(10);                  // number of architectures
24835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  AppendDummyArchEntries(10);
24935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFat(false);
25035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
25135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
25235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(FatReaderTest, HeaderTooShort) {
25335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_CALL(reporter, TooShort()).Times(1);
25435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  fat
25535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .B32(0xcafebabe);             // magic number
25635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFat(false);
25735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
25835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
25935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(FatReaderTest, ObjectListTooShort) {
26035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_CALL(reporter, TooShort()).Times(1);
26135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  fat
26235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .B32(0xcafebabe)              // magic number
26335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .B32(10);                     // number of architectures
26435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  AppendDummyArchEntries(9);        // nine dummy architecture entries...
26535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  fat                               // and a tenth, missing a byte at the end
26635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .B32(0x3d46c8fc)              // cpu type
26735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .B32(0x8a7bfb01)              // cpu subtype
26835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .B32(0)                       // offset
26935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .B32(0)                       // size
27035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Append(3, '*');              // one byte short of a four-byte alignment
27135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFat(false);
27235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
27335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
27435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(FatReaderTest, DataTooShort) {
27535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_CALL(reporter, MisplacedObjectFile()).Times(1);
27635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Label arch_data;
27735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  fat
27835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .B32(0xcafebabe)              // magic number
27935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .B32(1);                      // number of architectures
28035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  AppendFatArch(0xb4d4a366, 0x4ba4f525, arch_data, 40, 0);
28135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  fat
28235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Mark(&arch_data)             // file data begins here
28335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Append(30, '*');             // only 30 bytes, not 40 as header claims
28435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFat(false);
28535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
28635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
28735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(FatReaderTest, NoObjectFiles) {
28835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  fat
28935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .B32(0xcafebabe)              // magic number
29035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .B32(0);                      // number of architectures
29135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFat();
29235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0U, object_files_size);
29335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
29435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
29535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(FatReaderTest, OneObjectFile) {
29635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Label obj1_offset;
29735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  fat
29835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .B32(0xcafebabe)              // magic number
29935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .B32(1);                      // number of architectures
30035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // First object file list entry
30135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  AppendFatArch(0x5e3a6e91, 0x52ccd852, obj1_offset, 0x42, 0x355b15b2);
30235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // First object file data
30335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  fat
30435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Mark(&obj1_offset)
30535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Append(0x42, '*');           // dummy contents
30635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFat();
30735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ASSERT_EQ(1U, object_files_size);
30835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x5e3a6e91, object_files[0].cputype);
30935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x52ccd852, object_files[0].cpusubtype);
31035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(obj1_offset.Value(), object_files[0].offset);
31135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x42U, object_files[0].size);
31235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x355b15b2U, object_files[0].align);
31335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
31435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
31535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(FatReaderTest, ThreeObjectFiles) {
31635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Label obj1, obj2, obj3;
31735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  fat
31835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .B32(0xcafebabe)              // magic number
31935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .B32(3);                      // number of architectures
32035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Three object file list entries.
32135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  AppendFatArch(0x0cb92c30, 0x6a159a71, obj1, 0xfb4, 0x2615dbe8);
32235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  AppendFatArch(0x0f3f1cbb, 0x6c55e90f, obj2, 0xc31, 0x83af6ffd);
32335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  AppendFatArch(0x3717276d, 0x10ecdc84, obj3, 0x4b3, 0x035267d7);
32435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  fat
32535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      // First object file data
32635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Mark(&obj1)
32735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Append(0xfb4, '*')           // dummy contents
32835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      // Second object file data
32935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Mark(&obj2)
33035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Append(0xc31, '%')           // dummy contents
33135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      // Third object file data
33235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Mark(&obj3)
33335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Append(0x4b3, '^');          // dummy contents
33435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
33535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFat();
33635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
33735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ASSERT_EQ(3U, object_files_size);
33835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
33935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // First object file.
34035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x0cb92c30, object_files[0].cputype);
34135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x6a159a71, object_files[0].cpusubtype);
34235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(obj1.Value(), object_files[0].offset);
34335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0xfb4U, object_files[0].size);
34435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x2615dbe8U, object_files[0].align);
34535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
34635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Second object file.
34735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x0f3f1cbb, object_files[1].cputype);
34835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x6c55e90f, object_files[1].cpusubtype);
34935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(obj2.Value(), object_files[1].offset);
35035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0xc31U, object_files[1].size);
35135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x83af6ffdU, object_files[1].align);
35235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
35335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Third object file.
35435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x3717276d, object_files[2].cputype);
35535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x10ecdc84, object_files[2].cpusubtype);
35635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(obj3.Value(), object_files[2].offset);
35735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x4b3U, object_files[2].size);
35835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x035267d7U, object_files[2].align);
35935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
36035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
36135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(FatReaderTest, BigEndianMachO32) {
36235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  fat.set_endianness(kBigEndian);
36335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  fat
36435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0xfeedface)                  // Mach-O file magic number
36535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x1a9d0518)                  // cpu type
36635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x1b779357)                  // cpu subtype
36735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x009df67e)                  // file type
36835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0)                           // no load commands
36935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0)                           // the load commands occupy no bytes
37035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x21987a99);                 // flags
37135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
37235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFat();
37335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
37435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // FatReader should treat a Mach-O file as if it were a fat binary file
37535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // containing one object file --- the whole thing.
37635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ASSERT_EQ(1U, object_files_size);
37735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x1a9d0518, object_files[0].cputype);
37835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x1b779357, object_files[0].cpusubtype);
37935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0U, object_files[0].offset);
38035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(contents.size(), object_files[0].size);
38135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
38235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
38335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(FatReaderTest, BigEndianMachO64) {
38435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  fat.set_endianness(kBigEndian);
38535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  fat
38635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0xfeedfacf)                  // Mach-O 64-bit file magic number
38735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x5aff8487)                  // cpu type
38835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x4c6a57f7)                  // cpu subtype
38935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x4392d2c8)                  // file type
39035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0)                           // no load commands
39135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0)                           // the load commands occupy no bytes
39235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x1b033eea);                 // flags
39335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
39435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFat();
39535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
39635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // FatReader should treat a Mach-O file as if it were a fat binary file
39735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // containing one object file --- the whole thing.
39835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ASSERT_EQ(1U, object_files_size);
39935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x5aff8487, object_files[0].cputype);
40035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x4c6a57f7, object_files[0].cpusubtype);
40135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0U, object_files[0].offset);
40235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(contents.size(), object_files[0].size);
40335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
40435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
40535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(FatReaderTest, LittleEndianMachO32) {
40635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  fat.set_endianness(kLittleEndian);
40735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  fat
40835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0xfeedface)                  // Mach-O file magic number
40935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x1a9d0518)                  // cpu type
41035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x1b779357)                  // cpu subtype
41135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x009df67e)                  // file type
41235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0)                           // no load commands
41335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0)                           // the load commands occupy no bytes
41435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x21987a99);                 // flags
41535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
41635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFat();
41735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
41835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // FatReader should treat a Mach-O file as if it were a fat binary file
41935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // containing one object file --- the whole thing.
42035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ASSERT_EQ(1U, object_files_size);
42135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x1a9d0518, object_files[0].cputype);
42235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x1b779357, object_files[0].cpusubtype);
42335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0U, object_files[0].offset);
42435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(contents.size(), object_files[0].size);
42535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
42635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
42735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(FatReaderTest, LittleEndianMachO64) {
42835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  fat.set_endianness(kLittleEndian);
42935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  fat
43035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0xfeedfacf)                  // Mach-O 64-bit file magic number
43135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x5aff8487)                  // cpu type
43235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x4c6a57f7)                  // cpu subtype
43335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x4392d2c8)                  // file type
43435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0)                           // no load commands
43535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0)                           // the load commands occupy no bytes
43635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x1b033eea);                 // flags
43735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
43835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFat();
43935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
44035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // FatReader should treat a Mach-O file as if it were a fat binary file
44135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // containing one object file --- the whole thing.
44235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ASSERT_EQ(1U, object_files_size);
44335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x5aff8487, object_files[0].cputype);
44435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x4c6a57f7, object_files[0].cpusubtype);
44535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0U, object_files[0].offset);
44635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(contents.size(), object_files[0].size);
44735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
44835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
44935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(FatReaderTest, IncompleteMach) {
45035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  fat.set_endianness(kLittleEndian);
45135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  fat
45235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0xfeedfacf)                  // Mach-O 64-bit file magic number
45335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x5aff8487);                 // cpu type
45435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      // Truncated!
45535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
45635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_CALL(reporter, TooShort()).WillOnce(Return());
45735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
45835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFat(false);
45935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
46035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
46135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
46235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// General mach_o::Reader tests.
46335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
46435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// Dynamically scoped configuration data.
46535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekclass WithConfiguration {
46635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek public:
46735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Establish the given parameters as the default for SizedSections
46835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // created within the dynamic scope of this instance.
46935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration(Endianness endianness, size_t word_size)
47035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      : endianness_(endianness), word_size_(word_size), saved_(current_) {
47135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    current_ = this;
47235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  }
47335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ~WithConfiguration() { current_ = saved_; }
47435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  static Endianness endianness() {
47535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    assert(current_);
47635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    return current_->endianness_;
47735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  }
47835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  static size_t word_size() {
47935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    assert(current_);
48035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    return current_->word_size_;
48135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  }
48235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
48335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek private:
48435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // The innermost WithConfiguration in whose dynamic scope we are
48535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // currently executing.
48635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  static WithConfiguration *current_;
48735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
48835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // The innermost WithConfiguration whose dynamic scope encloses this
48935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // WithConfiguration.
49035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Endianness endianness_;
49135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  size_t word_size_;
49235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration *saved_;
49335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek};
49435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
49535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekWithConfiguration *WithConfiguration::current_ = NULL;
49635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
49735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// A test_assembler::Section with a size that we can cite. The start(),
49835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// Here() and Mark() member functions of a SizedSection always represent
49935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// offsets within the overall file.
50035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekclass SizedSection: public test_assembler::Section {
50135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek public:
50235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Construct a section of the given endianness and word size.
50335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  explicit SizedSection(Endianness endianness, size_t word_size)
50435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      : test_assembler::Section(endianness), word_size_(word_size) {
50535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    assert(word_size_ == 32 || word_size_ == 64);
50635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  }
50735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  SizedSection()
50835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      : test_assembler::Section(WithConfiguration::endianness()),
50935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek        word_size_(WithConfiguration::word_size()) {
51035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    assert(word_size_ == 32 || word_size_ == 64);
51135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  }
51235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
51335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Access/set this section's word size.
51435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  size_t word_size() const { return word_size_; }
51535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  void set_word_size(size_t word_size) {
51635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    assert(word_size_ == 32 || word_size_ == 64);
51735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    word_size_ = word_size;
51835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  }
51935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
52035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Return a label representing the size this section will have when it
52135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // is Placed in some containing section.
52235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Label final_size() const { return final_size_; }
52335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
52435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Append SECTION to the end of this section, and call its Finish member.
52535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Return a reference to this section.
52635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  SizedSection &Place(SizedSection *section) {
52735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    assert(section->endianness() == endianness());
52835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    section->Finish();
52935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    section->start() = Here();
53035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    test_assembler::Section::Append(*section);
53135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    return *this;
53235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  }
53335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
53435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek protected:
53535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Mark this section's contents as complete. For plain SizedSections, we
53635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // set SECTION's start to its position in this section, and its final_size
53735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // label to its current size. Derived classes can extend this as needed
53835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // for their additional semantics.
53935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  virtual void Finish() {
54035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    final_size_ = Size();
54135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  }
54235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
54335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // The word size for this data: either 32 or 64.
54435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  size_t word_size_;
54535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
54635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek private:
54735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // This section's final size, set when we are placed in some other
54835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // SizedSection.
54935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Label final_size_;
55035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek};
55135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
55235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// A SizedSection that is loaded into memory at a particular address.
55335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekclass LoadedSection: public SizedSection {
55435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek public:
55535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  explicit LoadedSection(Label address = Label()) : address_(address) { }
55635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
55735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Return a label representing this section's address.
55835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Label address() const { return address_; }
55935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
56035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Placing a loaded section within a loaded section sets the relationship
56135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // between their addresses.
56235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadedSection &Place(LoadedSection *section) {
56335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    section->address() = address() + Size();
56435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    SizedSection::Place(section);
56535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    return *this;
56635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  }
56735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
56835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek protected:
56935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // The address at which this section's contents will be loaded.
57035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Label address_;
57135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek};
57235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
57335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// A SizedSection representing a segment load command.
57435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekclass SegmentLoadCommand: public SizedSection {
57535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek public:
57635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  SegmentLoadCommand() : section_count_(0) { }
57735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
57835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Append a segment load command header with the given characteristics.
57935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // The load command will refer to CONTENTS, which must be Placed in the
58035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // file separately, at the desired position. Return a reference to this
58135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // section.
58235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  SegmentLoadCommand &Header(const string &name, const LoadedSection &contents,
58335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                             uint32_t maxprot, uint32_t initprot,
58435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                             uint32_t flags) {
58535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    assert(contents.word_size() == word_size());
58635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    D32(word_size() == 32 ? LC_SEGMENT : LC_SEGMENT_64);
58735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    D32(final_size());
58835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    AppendCString(name, 16);
58935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    Append(endianness(), word_size() / 8, contents.address());
59035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    Append(endianness(), word_size() / 8, vmsize_);
59135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    Append(endianness(), word_size() / 8, contents.start());
59235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    Append(endianness(), word_size() / 8, contents.final_size());
59335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    D32(maxprot);
59435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    D32(initprot);
59535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    D32(final_section_count_);
59635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    D32(flags);
59735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
59835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    content_final_size_ = contents.final_size();
59935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
60035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    return *this;
60135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  }
60235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
60335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Return a label representing the size of this segment when loaded into
60435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // memory. If this label is still undefined by the time we place this
60535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // segment, it defaults to the final size of the segment's in-file
60635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // contents. Return a reference to this load command.
60735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Label &vmsize() { return vmsize_; }
60835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
60935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Add a section entry with the given characteristics to this segment
61035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // load command. Return a reference to this. The section entry will refer
61135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // to CONTENTS, which must be Placed in the segment's contents
61235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // separately, at the desired position.
61335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  SegmentLoadCommand &AppendSectionEntry(const string &section_name,
61435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                                         const string &segment_name,
61535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                                         uint32_t alignment, uint32_t flags,
61635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                                         const LoadedSection &contents) {
61735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    AppendCString(section_name, 16);
61835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    AppendCString(segment_name, 16);
61935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    Append(endianness(), word_size() / 8, contents.address());
62035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    Append(endianness(), word_size() / 8, contents.final_size());
62135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    D32(contents.start());
62235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    D32(alignment);
62335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    D32(0);                  // relocations start
62435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    D32(0);                  // relocations size
62535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    D32(flags);
62635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    D32(0x93656b95);         // reserved1
62735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    D32(0xc35a2473);         // reserved2
62835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    if (word_size() == 64)
62935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      D32(0x70284b95);       // reserved3
63035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
63135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    section_count_++;
63235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
63335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    return *this;
63435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  }
63535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
63635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek protected:
63735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  void Finish() {
63835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    final_section_count_ = section_count_;
63935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    if (!vmsize_.IsKnownConstant())
64035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      vmsize_ = content_final_size_;
64135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    SizedSection::Finish();
64235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  }
64335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
64435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek private:
64535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // The number of sections that have been added to this segment so far.
64635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  size_t section_count_;
64735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
64835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // A label representing the final number of sections this segment will hold.
64935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Label final_section_count_;
65035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
65135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // The size of the contents for this segment present in the file.
65235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Label content_final_size_;
65335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
65435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // A label representing the size of this segment when loaded; this can be
65535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // larger than the size of its file contents, the difference being
65635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // zero-filled. If not set explicitly by calling set_vmsize, this is set
65735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // equal to the size of the contents.
65835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Label vmsize_;
65935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek};
66035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
66135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// A SizedSection holding a list of Mach-O load commands.
66235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekclass LoadCommands: public SizedSection {
66335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek public:
66435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadCommands() : command_count_(0) { }
66535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
66635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Return a label representing the final load command count.
66735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Label final_command_count() const { return final_command_count_; }
66835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
66935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Increment the command count; return a reference to this section.
67035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadCommands &CountCommand() {
67135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    command_count_++;
67235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    return *this;
67335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  }
67435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
67535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Place COMMAND, containing a load command, at the end of this section.
67635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Return a reference to this section.
67735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadCommands &Place(SizedSection *section) {
67835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    SizedSection::Place(section);
67935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    CountCommand();
68035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    return *this;
68135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  }
68235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
68335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek protected:
68435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Mark this load command list as complete.
68535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  void Finish() {
68635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    SizedSection::Finish();
68735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    final_command_count_ = command_count_;
68835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  }
68935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
69035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek private:
69135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // The number of load commands we have added to this file so far.
69235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  size_t command_count_;
69335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
69435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // A label representing the final command count.
69535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Label final_command_count_;
69635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek};
69735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
69835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// A SizedSection holding the contents of a Mach-O file. Within a
69935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// MachOFile, the start, Here, and Mark members refer to file offsets.
70035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekclass MachOFile: public SizedSection {
70135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek public:
70235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile() {
70335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    start() = 0;
70435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  }
70535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
70635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Create a Mach-O file header using the given characteristics and load
70735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // command list. This Places COMMANDS immediately after the header.
70835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Return a reference to this section.
70935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile &Header(LoadCommands *commands,
71035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                    cpu_type_t cpu_type = CPU_TYPE_X86,
71135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                    cpu_subtype_t cpu_subtype = CPU_SUBTYPE_I386_ALL,
71235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                    FileType file_type = MH_EXECUTE,
71335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                    uint32_t file_flags = (MH_TWOLEVEL |
71435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                                           MH_DYLDLINK |
71535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                                           MH_NOUNDEFS)) {
71635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    D32(word_size() == 32 ? 0xfeedface : 0xfeedfacf);  // magic number
71735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    D32(cpu_type);                              // cpu type
71835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    D32(cpu_subtype);                           // cpu subtype
71935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    D32(file_type);                             // file type
72035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    D32(commands->final_command_count());       // number of load commands
72135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    D32(commands->final_size());                // their size in bytes
72235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    D32(file_flags);                            // flags
72335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    if (word_size() == 64)
72435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      D32(0x55638b90);                          // reserved
72535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    Place(commands);
72635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    return *this;
72735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  }
72835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek};
72935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
73035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
73135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekstruct ReaderFixture {
73235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReaderFixture()
73335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      : reporter("reporter filename"),
73435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek        reader(&reporter) {
73535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    EXPECT_CALL(reporter, BadHeader()).Times(0);
73635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    EXPECT_CALL(reporter, CPUTypeMismatch(_, _, _, _)).Times(0);
73735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    EXPECT_CALL(reporter, HeaderTruncated()).Times(0);
73835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    EXPECT_CALL(reporter, LoadCommandRegionTruncated()).Times(0);
73935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    EXPECT_CALL(reporter, LoadCommandsOverrun(_, _, _)).Times(0);
74035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    EXPECT_CALL(reporter, LoadCommandTooShort(_, _)).Times(0);
74135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    EXPECT_CALL(reporter, SectionsMissing(_)).Times(0);
74235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    EXPECT_CALL(reporter, MisplacedSegmentData(_)).Times(0);
74335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    EXPECT_CALL(reporter, MisplacedSectionData(_, _)).Times(0);
74435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    EXPECT_CALL(reporter, MisplacedSymbolTable()).Times(0);
74535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    EXPECT_CALL(reporter, UnsupportedCPUType(_)).Times(0);
74635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
74735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    EXPECT_CALL(load_command_handler, UnknownCommand(_, _)).Times(0);
74835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    EXPECT_CALL(load_command_handler, SegmentCommand(_)).Times(0);
74935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  }
75035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
75135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  void ReadFile(MachOFile *file,
75235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                bool expect_parse_success,
75335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                cpu_type_t expected_cpu_type,
75435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                cpu_subtype_t expected_cpu_subtype) {
75535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    ASSERT_TRUE(file->GetContents(&file_contents));
75635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    file_bytes = reinterpret_cast<const uint8_t *>(file_contents.data());
75735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    if (expect_parse_success) {
75835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      EXPECT_TRUE(reader.Read(file_bytes,
75935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                              file_contents.size(),
76035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                              expected_cpu_type,
76135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                              expected_cpu_subtype));
76235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    } else {
76335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      EXPECT_FALSE(reader.Read(file_bytes,
76435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                               file_contents.size(),
76535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                               expected_cpu_type,
76635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                               expected_cpu_subtype));
76735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    }
76835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  }
76935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
77035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  string file_contents;
77135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  const uint8_t *file_bytes;
77235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MockReaderReporter reporter;
77335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Reader reader;
77435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MockLoadCommandHandler load_command_handler;
77535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MockSectionHandler section_handler;
77635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek};
77735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
77835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekclass ReaderTest: public ReaderFixture, public Test { };
77935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
78035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(ReaderTest, BadMagic) {
78135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kLittleEndian, 32);
78235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  const cpu_type_t kCPUType = 0x46b760df;
78335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  const cpu_subtype_t kCPUSubType = 0x76a0e7f7;
78435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
78535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file
78635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x67bdebe1)                  // Not a proper magic number.
78735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(kCPUType)                    // cpu type
78835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(kCPUSubType)                 // cpu subtype
78935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x149fc717)                  // file type
79035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0)                           // no load commands
79135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0)                           // they occupy no bytes
79235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x80e71d64)                  // flags
79335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0);                          // reserved
79435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_CALL(reporter, BadHeader()).WillOnce(Return());
79535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFile(&file, false, CPU_TYPE_ANY, kCPUSubType);
79635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
79735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
79835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(ReaderTest, MismatchedMagic) {
79935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kLittleEndian, 32);
80035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  const cpu_type_t kCPUType = CPU_TYPE_I386;
80135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  const cpu_subtype_t kCPUSubType = CPU_SUBTYPE_X86_ALL;
80235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
80335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file
80435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(MH_CIGAM)                    // Right magic, but winds up wrong
80535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                                        // due to bitswapping
80635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(kCPUType)                    // cpu type
80735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(kCPUSubType)                 // cpu subtype
80835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x149fc717)                  // file type
80935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0)                           // no load commands
81035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0)                           // they occupy no bytes
81135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x80e71d64)                  // flags
81235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0);                          // reserved
81335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_CALL(reporter, BadHeader()).WillOnce(Return());
81435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFile(&file, false, kCPUType, kCPUSubType);
81535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
81635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
81735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(ReaderTest, ShortMagic) {
81835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kBigEndian, 32);
81935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
82035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file
82135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D16(0xfeed);                     // magic number
82235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                                        // truncated!
82335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_CALL(reporter, HeaderTruncated()).WillOnce(Return());
82435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFile(&file, false, CPU_TYPE_ANY, 0);
82535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
82635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
82735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(ReaderTest, ShortHeader) {
82835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kBigEndian, 32);
82935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  const cpu_type_t kCPUType = CPU_TYPE_ANY;
83035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  const cpu_subtype_t kCPUSubType = 0x76a0e7f7;
83135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
83235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file
83335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0xfeedface)                  // magic number
83435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(kCPUType)                    // cpu type
83535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(kCPUSubType)                 // cpu subtype
83635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x149fc717)                  // file type
83735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0)                           // no load commands
83835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0);                          // they occupy no bytes
83935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_CALL(reporter, HeaderTruncated()).WillOnce(Return());
84035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFile(&file, false, CPU_TYPE_ANY, kCPUSubType);
84135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
84235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
84335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(ReaderTest, MismatchedCPU) {
84435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kBigEndian, 32);
84535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  const cpu_type_t kCPUType = CPU_TYPE_I386;
84635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  const cpu_subtype_t kCPUSubType = CPU_SUBTYPE_X86_ALL;
84735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
84835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file
84935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(MH_MAGIC)                    // Right magic for PPC (once bitswapped)
85035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(kCPUType)                    // cpu type
85135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(kCPUSubType)                 // cpu subtype
85235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x149fc717)                  // file type
85335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0)                           // no load commands
85435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0)                           // they occupy no bytes
85535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x80e71d64)                  // flags
85635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0);                          // reserved
85735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_CALL(reporter,
85835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek              CPUTypeMismatch(CPU_TYPE_I386, CPU_SUBTYPE_X86_ALL,
85935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                              CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_ALL))
86035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    .WillOnce(Return());
86135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFile(&file, false, CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_ALL);
86235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
86335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
86435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(ReaderTest, LittleEndian32Bit) {
86535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kLittleEndian, 32);
86635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  const cpu_type_t kCPUType = 0x46b760df;
86735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  const cpu_subtype_t kCPUSubType = 0x76a0e7f7;
86835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
86935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file
87035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0xfeedface)                  // magic number
87135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(kCPUType)                    // cpu type
87235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(kCPUSubType)                 // cpu subtype
87335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x149fc717)                  // file type
87435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0)                           // no load commands
87535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0)                           // they occupy no bytes
87635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x80e71d64)                  // flags
87735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0);                          // reserved
87835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek           ReadFile(&file, true, CPU_TYPE_ANY, kCPUSubType);
87935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_FALSE(reader.bits_64());
88035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_FALSE(reader.big_endian());
88135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(kCPUType,               reader.cpu_type());
88235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(kCPUSubType,            reader.cpu_subtype());
88335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(FileType(0x149fc717),   reader.file_type());
88435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(FileFlags(0x80e71d64),  reader.flags());
88535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
88635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
88735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(ReaderTest, LittleEndian64Bit) {
88835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kLittleEndian, 64);
88935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  const cpu_type_t kCPUType = 0x46b760df;
89035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  const cpu_subtype_t kCPUSubType = 0x76a0e7f7;
89135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
89235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file
89335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0xfeedfacf)                  // magic number
89435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(kCPUType)                    // cpu type
89535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(kCPUSubType)                 // cpu subtype
89635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x149fc717)                  // file type
89735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0)                           // no load commands
89835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0)                           // they occupy no bytes
89935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x80e71d64)                  // flags
90035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0);                          // reserved
90135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFile(&file, true, CPU_TYPE_ANY, kCPUSubType);
90235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_TRUE(reader.bits_64());
90335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_FALSE(reader.big_endian());
90435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(kCPUType,               reader.cpu_type());
90535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(kCPUSubType,            reader.cpu_subtype());
90635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(FileType(0x149fc717),   reader.file_type());
90735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(FileFlags(0x80e71d64),  reader.flags());
90835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
90935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
91035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(ReaderTest, BigEndian32Bit) {
91135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kBigEndian, 32);
91235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  const cpu_type_t kCPUType = 0x46b760df;
91335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  const cpu_subtype_t kCPUSubType = 0x76a0e7f7;
91435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
91535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file
91635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0xfeedface)                  // magic number
91735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(kCPUType)                    // cpu type
91835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(kCPUSubType)                 // cpu subtype
91935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x149fc717)                  // file type
92035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0)                           // no load commands
92135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0)                           // they occupy no bytes
92235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x80e71d64)                  // flags
92335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0);                          // reserved
92435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFile(&file, true, CPU_TYPE_ANY, kCPUSubType);
92535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_FALSE(reader.bits_64());
92635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_TRUE(reader.big_endian());
92735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(kCPUType,               reader.cpu_type());
92835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(kCPUSubType,            reader.cpu_subtype());
92935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(FileType(0x149fc717),   reader.file_type());
93035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(FileFlags(0x80e71d64),  reader.flags());
93135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
93235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
93335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(ReaderTest, BigEndian64Bit) {
93435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kBigEndian, 64);
93535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  const cpu_type_t kCPUType = 0x46b760df;
93635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  const cpu_subtype_t kCPUSubType = 0x76a0e7f7;
93735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
93835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file
93935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0xfeedfacf)                  // magic number
94035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(kCPUType)                    // cpu type
94135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(kCPUSubType)                 // cpu subtype
94235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x149fc717)                  // file type
94335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0)                           // no load commands
94435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0)                           // they occupy no bytes
94535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x80e71d64)                  // flags
94635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0);                          // reserved
94735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFile(&file, true, CPU_TYPE_ANY, kCPUSubType);
94835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_TRUE(reader.bits_64());
94935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_TRUE(reader.big_endian());
95035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(kCPUType,               reader.cpu_type());
95135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(kCPUSubType,            reader.cpu_subtype());
95235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(FileType(0x149fc717),   reader.file_type());
95335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(FileFlags(0x80e71d64),  reader.flags());
95435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
95535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
95635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
95735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// Load command tests.
95835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
95935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekclass LoadCommand: public ReaderFixture, public Test { };
96035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
96135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(LoadCommand, RegionTruncated) {
96235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kBigEndian, 64);
96335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  const cpu_type_t kCPUType = 0x46b760df;
96435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  const cpu_subtype_t kCPUSubType = 0x76a0e7f7;
96535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
96635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file
96735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0xfeedfacf)                  // magic number
96835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(kCPUType)                    // cpu type
96935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(kCPUSubType)                 // cpu subtype
97035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x149fc717)                  // file type
97135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(1)                           // one load command
97235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(40)                          // occupying 40 bytes
97335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x80e71d64)                  // flags
97435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0)                           // reserved
97535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Append(20, 0);                   // load command region, not as long as
97635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                                        // Mach-O header promised
97735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
97835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_CALL(reporter, LoadCommandRegionTruncated()).WillOnce(Return());
97935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
98035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFile(&file, false, CPU_TYPE_ANY, kCPUSubType);
98135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
98235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
98335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(LoadCommand, None) {
98435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kLittleEndian, 32);
98535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadCommands load_commands;
98635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
98735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file.Header(&load_commands);
98835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
98935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFile(&file, true, CPU_TYPE_X86, CPU_SUBTYPE_I386_ALL);
99035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
99135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_FALSE(reader.bits_64());
99235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_FALSE(reader.big_endian());
99335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(CPU_TYPE_X86,         reader.cpu_type());
99435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(CPU_SUBTYPE_I386_ALL, reader.cpu_subtype());
9954ac61acb3a7dad6ce722fe07564be8ec92713228dmaclach  EXPECT_EQ(static_cast<uint32_t>(MH_EXECUTE), reader.file_type());
99635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(FileFlags(MH_TWOLEVEL |
99735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                      MH_DYLDLINK |
99835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                      MH_NOUNDEFS),
99935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek            FileFlags(reader.flags()));
100035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
100135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_TRUE(reader.WalkLoadCommands(&load_command_handler));
100235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
100335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
100435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(LoadCommand, Unknown) {
100535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kBigEndian, 32);
100635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadCommands load_commands;
100735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  load_commands
100835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .CountCommand()
100935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x33293d4a)                  // unknown load command
101035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(40)                          // total size in bytes
101135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Append(32, '*');                 // dummy data
101235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
101335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file.Header(&load_commands);
101435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
101535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFile(&file, true, CPU_TYPE_ANY, 0);
101635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
101735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_FALSE(reader.bits_64());
101835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_TRUE(reader.big_endian());
101935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(CPU_TYPE_X86,         reader.cpu_type());
102035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(CPU_SUBTYPE_I386_ALL, reader.cpu_subtype());
10214ac61acb3a7dad6ce722fe07564be8ec92713228dmaclach  EXPECT_EQ(static_cast<uint32_t>(MH_EXECUTE), reader.file_type());
102235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(FileFlags(MH_TWOLEVEL |
102335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                      MH_DYLDLINK |
102435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                      MH_NOUNDEFS),
102535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek            reader.flags());
102635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
102735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ByteBuffer expected;
102835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  expected.start = file_bytes + load_commands.start().Value();
102935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  expected.end = expected.start + load_commands.final_size().Value();
103035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_CALL(load_command_handler, UnknownCommand(0x33293d4a,
103135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                                                   expected))
103235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .WillOnce(Return(true));
103335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
103435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_TRUE(reader.WalkLoadCommands(&load_command_handler));
103535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
103635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
103735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(LoadCommand, TypeIncomplete) {
103835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kLittleEndian, 32);
103935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadCommands load_commands;
104035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  load_commands
104135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .CountCommand()
104235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Append(3, 0);                    // load command type, incomplete
104335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
104435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
104535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file.Header(&load_commands);
104635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
104735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFile(&file, true, CPU_TYPE_ANY, 0);
104835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
104935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_CALL(reporter, LoadCommandsOverrun(1, 0, 0))
105035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .WillOnce(Return());
105135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_FALSE(reader.WalkLoadCommands(&load_command_handler));
105235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
105335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
105435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(LoadCommand, LengthIncomplete) {
105535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kBigEndian, 64);
105635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadCommands load_commands;
105735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  load_commands
105835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .CountCommand()
105935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(LC_SEGMENT);                 // load command
106035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                                                // no length
106135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
106235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file.Header(&load_commands);
106335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
106435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFile(&file, true, CPU_TYPE_ANY, 0);
106535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
106635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_CALL(reporter, LoadCommandsOverrun(1, 0, LC_SEGMENT))
106735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .WillOnce(Return());
106835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_FALSE(reader.WalkLoadCommands(&load_command_handler));
106935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
107035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
107135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(LoadCommand, ContentIncomplete) {
107235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kLittleEndian, 64);
107335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadCommands load_commands;
107435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  load_commands
107535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .CountCommand()
107635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(LC_SEGMENT)          // load command
107735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(40)                          // total size in bytes
107835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Append(28, '*');                 // not enough dummy data
107935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
108035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file.Header(&load_commands);
108135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
108235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFile(&file, true, CPU_TYPE_ANY, 0);
108335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
108435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_CALL(reporter, LoadCommandsOverrun(1, 0, LC_SEGMENT))
108535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .WillOnce(Return());
108635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_FALSE(reader.WalkLoadCommands(&load_command_handler));
108735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
108835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
108935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(LoadCommand, SegmentBE32) {
109035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kBigEndian, 32);
109135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadedSection segment;
109235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment.address() = 0x1891139c;
109335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment.Append(42, '*');              // segment contents
109435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  SegmentLoadCommand segment_command;
109535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment_command
109635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Header("froon", segment, 0x94d6dd22, 0x8bdbc319, 0x990a16dd);
109735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment_command.vmsize() = 0xcb76584fU;
109835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadCommands load_commands;
109935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  load_commands.Place(&segment_command);
110035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
110135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file
110235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Header(&load_commands)
110335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Place(&segment);
110435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
110535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFile(&file, true, CPU_TYPE_ANY, 0);
110635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
110735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Segment actual_segment;
110835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_CALL(load_command_handler, SegmentCommand(_))
110935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    .WillOnce(DoAll(SaveArg<0>(&actual_segment),
111035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                    Return(true)));
111135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_TRUE(reader.WalkLoadCommands(&load_command_handler));
111235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
111335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(false,                        actual_segment.bits_64);
111435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ("froon",                      actual_segment.name);
111535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x1891139cU,                  actual_segment.vmaddr);
111635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0xcb76584fU,                  actual_segment.vmsize);
111735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x94d6dd22U,                  actual_segment.maxprot);
111835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x8bdbc319U,                  actual_segment.initprot);
111935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x990a16ddU,                  actual_segment.flags);
112035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0U,                           actual_segment.nsects);
112135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0U,                           actual_segment.section_list.Size());
112235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(segment.final_size().Value(), actual_segment.contents.Size());
112335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
112435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
112535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(LoadCommand, SegmentLE32) {
112635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kLittleEndian, 32);
112735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadedSection segment;
112835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment.address() = 0x4b877866;
112935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment.Append(42, '*');              // segment contents
113035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  SegmentLoadCommand segment_command;
113135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment_command
113235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Header("sixteenprecisely", segment,
113335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek              0x350759ed, 0x6cf5a62e, 0x990a16dd);
113435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment_command.vmsize() = 0xcb76584fU;
113535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadCommands load_commands;
113635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  load_commands.Place(&segment_command);
113735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
113835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file
113935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Header(&load_commands)
114035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Place(&segment);
114135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
114235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFile(&file, true, CPU_TYPE_ANY, 0);
114335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
114435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Segment actual_segment;
114535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_CALL(load_command_handler, SegmentCommand(_))
114635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    .WillOnce(DoAll(SaveArg<0>(&actual_segment),
114735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                    Return(true)));
114835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_TRUE(reader.WalkLoadCommands(&load_command_handler));
114935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
115035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(false,                        actual_segment.bits_64);
115135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ("sixteenprecisely",           actual_segment.name);
115235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x4b877866U,                  actual_segment.vmaddr);
115335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0xcb76584fU,                  actual_segment.vmsize);
115435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x350759edU,                  actual_segment.maxprot);
115535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x6cf5a62eU,                  actual_segment.initprot);
115635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x990a16ddU,                  actual_segment.flags);
115735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0U,                           actual_segment.nsects);
115835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0U,                           actual_segment.section_list.Size());
115935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(segment.final_size().Value(), actual_segment.contents.Size());
116035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
116135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
116235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(LoadCommand, SegmentBE64) {
116335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kBigEndian, 64);
116435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadedSection segment;
116535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment.address() = 0x79f484f77009e511ULL;
116635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment.Append(42, '*');              // segment contents
116735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  SegmentLoadCommand segment_command;
116835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment_command
116935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Header("froon", segment, 0x42b45da5, 0x8bdbc319, 0xb2335220);
117035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment_command.vmsize() = 0x8d92397ce6248abaULL;
117135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadCommands load_commands;
117235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  load_commands.Place(&segment_command);
117335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
117435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file
117535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Header(&load_commands)
117635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Place(&segment);
117735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
117835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFile(&file, true, CPU_TYPE_ANY, 0);
117935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
118035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Segment actual_segment;
118135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_CALL(load_command_handler, SegmentCommand(_))
118235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    .WillOnce(DoAll(SaveArg<0>(&actual_segment),
118335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                    Return(true)));
118435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_TRUE(reader.WalkLoadCommands(&load_command_handler));
118535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
118635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(true,                         actual_segment.bits_64);
118735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ("froon",                      actual_segment.name);
118835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x79f484f77009e511ULL,        actual_segment.vmaddr);
118935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x8d92397ce6248abaULL,        actual_segment.vmsize);
119035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x42b45da5U,                  actual_segment.maxprot);
119135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x8bdbc319U,                  actual_segment.initprot);
119235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0xb2335220U,                  actual_segment.flags);
119335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0U,                           actual_segment.nsects);
119435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0U,                           actual_segment.section_list.Size());
119535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(segment.final_size().Value(), actual_segment.contents.Size());
119635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
119735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
119835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(LoadCommand, SegmentLE64) {
119935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kLittleEndian, 64);
120035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadedSection segment;
120135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment.address() = 0x50c0501dc5922d35ULL;
120235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment.Append(42, '*');              // segment contents
120335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  SegmentLoadCommand segment_command;
120435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment_command
120535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Header("sixteenprecisely", segment,
120635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek              0x917c339d, 0xdbc446fa, 0xb650b563);
120735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment_command.vmsize() = 0x84ae73e7c75469bfULL;
120835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadCommands load_commands;
120935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  load_commands.Place(&segment_command);
121035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
121135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file
121235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Header(&load_commands)
121335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Place(&segment);
121435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
121535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFile(&file, true, CPU_TYPE_ANY, 0);
121635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
121735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Segment actual_segment;
121835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_CALL(load_command_handler, SegmentCommand(_))
121935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    .WillOnce(DoAll(SaveArg<0>(&actual_segment),
122035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                    Return(true)));
122135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_TRUE(reader.WalkLoadCommands(&load_command_handler));
122235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
122335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(true,                         actual_segment.bits_64);
122435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ("sixteenprecisely",           actual_segment.name);
122535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x50c0501dc5922d35ULL,        actual_segment.vmaddr);
122635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x84ae73e7c75469bfULL,        actual_segment.vmsize);
122735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0x917c339dU,                  actual_segment.maxprot);
122835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0xdbc446faU,                  actual_segment.initprot);
122935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0xb650b563U,                  actual_segment.flags);
123035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0U,                           actual_segment.nsects);
123135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0U,                           actual_segment.section_list.Size());
123235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(segment.final_size().Value(), actual_segment.contents.Size());
123335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
123435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
123535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(LoadCommand, SegmentCommandTruncated) {
123635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kBigEndian, 32);
123735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadedSection segment_contents;
123835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment_contents.Append(20, '*');     	// lah di dah
123935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  SizedSection command;
124035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  command
124135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(LC_SEGMENT)          	// command type
124235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(command.final_size())                // command size
124335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .AppendCString("too-short", 16)           // segment name
124435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x9c759211)                          // vmaddr
124535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(segment_contents.final_size())       // vmsize
124635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(segment_contents.start())            // file offset
124735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(segment_contents.final_size())       // file size
124835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0x56f28446)                          // max protection
124935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0xe7910dcb)                          // initial protection
125035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(0)                                   // no sections
125135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Append(3, 0);                            // flags (one byte short!)
125235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadCommands load_commands;
125335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  load_commands.Place(&command);
125435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
125535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file
125635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Header(&load_commands)
125735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Place(&segment_contents);
125835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
125935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFile(&file, true, CPU_TYPE_ANY, 0);
126035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
126135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_CALL(reporter, LoadCommandTooShort(0, LC_SEGMENT))
126235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .WillOnce(Return());
126335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
126435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_FALSE(reader.WalkLoadCommands(&load_command_handler));
126535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
126635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
126735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(LoadCommand, SegmentBadContentOffset) {
126835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kLittleEndian, 32);
126935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Instead of letting a Place call set the segment's file offset and size,
127035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // set them ourselves, to check that the parser catches invalid offsets
127135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // instead of handing us bogus pointers.
127235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadedSection segment;
127335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment.address() = 0x4db5489c;
127435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment.start() = 0x7e189e76;         // beyond end of file
127535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment.final_size() = 0x98b9c3ab;
127635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  SegmentLoadCommand segment_command;
127735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment_command
127835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Header("notmerelyfifteen", segment, 0xcbab25ee, 0x359a20db, 0x68a3933f);
127935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadCommands load_commands;
128035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  load_commands.Place(&segment_command);
128135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
128235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file.Header(&load_commands);
128335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
128435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFile(&file, true, CPU_TYPE_ANY, 0);
128535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
128635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_CALL(reporter, MisplacedSegmentData("notmerelyfifteen"))
128735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .WillOnce(Return());
128835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
128935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_FALSE(reader.WalkLoadCommands(&load_command_handler));
129035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
129135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
129235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(LoadCommand, ThreeLoadCommands) {
129335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kBigEndian, 32);
129435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadedSection seg1, seg2, seg3;
129535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  SegmentLoadCommand cmd1, cmd2, cmd3;
129635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
129735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  seg1.Append(128, '@');
129835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  seg1.address() = 0xa7f61ef6;
129935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  cmd1.Header("head", seg1, 0x88bf1cc7, 0x889a26a4, 0xe9b80d87);
130035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Include some dummy data at the end of the load command. Since we
130135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // didn't claim to have any sections, the reader should ignore this. But
130235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // making sure the commands have different lengths ensures that we're
130335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // using the right command's length to advance the LoadCommandIterator.
130435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  cmd1.Append(128, '!');
130535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
130635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  seg2.Append(42, '*');
130735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  seg2.address() = 0xc70fc909;
130835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  cmd2.Header("thorax", seg2, 0xde7327f4, 0xfdaf771d, 0x65e74b30);
130935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // More dummy data at the end of the load command.
131035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  cmd2.Append(32, '^');
131135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
131235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  seg3.Append(42, '%');
131335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  seg3.address() = 0x46b3ab05;
131435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  cmd3.Header("abdomen", seg3, 0x7098b70d, 0x8d8d7728, 0x5131419b);
131535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // More dummy data at the end of the load command.
131635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  cmd3.Append(64, '&');
131735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
131835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadCommands load_commands;
131935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  load_commands.Place(&cmd1).Place(&cmd2).Place(&cmd3);
132035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
132135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
132235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file.Header(&load_commands).Place(&seg1).Place(&seg2).Place(&seg3);
132335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
132435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFile(&file, true, CPU_TYPE_ANY, 0);
132535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
132635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  {
132735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    InSequence s;
132835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    EXPECT_CALL(load_command_handler,
132935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                SegmentCommand(Field(&Segment::name, "head")))
133035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .WillOnce(Return(true));
133135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    EXPECT_CALL(load_command_handler,
133235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                SegmentCommand(Field(&Segment::name, "thorax")))
133335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .WillOnce(Return(true));
133435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    EXPECT_CALL(load_command_handler,
133535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                SegmentCommand(Field(&Segment::name, "abdomen")))
133635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .WillOnce(Return(true));
133735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  }
133835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
133935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_TRUE(reader.WalkLoadCommands(&load_command_handler));
134035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
134135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
134235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekstatic inline Matcher<const Section &> MatchSection(
134335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    Matcher<bool> bits_64,
134435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    Matcher<const string &> section_name,
134535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    Matcher<const string &> segment_name,
134635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    Matcher<uint64_t> address,
134735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    Matcher<uint32_t> alignment,
134835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    Matcher<uint32_t> flags,
134935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    Matcher<const ByteBuffer &> contents) {
135035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  return AllOf(AllOf(Field(&Section::bits_64, bits_64),
135135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                     Field(&Section::section_name, section_name),
135235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                     Field(&Section::segment_name, segment_name),
135335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                     Field(&Section::address, address)),
135435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek               AllOf(Field(&Section::align, alignment),
135535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                     Field(&Section::flags, flags),
135635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                     Field(&Section::contents, contents)));
135735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
135835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
135935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekstatic inline Matcher<const Section &> MatchSection(
136035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    Matcher<bool> bits_64,
136135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    Matcher<const string &> section_name,
136235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    Matcher<const string &> segment_name,
136335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    Matcher<uint64_t> address) {
136435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  return AllOf(Field(&Section::bits_64, bits_64),
136535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek               Field(&Section::section_name, section_name),
136635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek               Field(&Section::segment_name, segment_name),
136735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek               Field(&Section::address, address));
136835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
136935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
137035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(LoadCommand, OneSegmentTwoSections) {
137135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kBigEndian, 64);
137235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
137335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Create some sections with some data.
137435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadedSection section1, section2;
137535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  section1.Append("buddha's hand");
137635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  section2.Append("kumquat");
137735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
137835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Create a segment to hold them.
137935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadedSection segment;
138035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment.address() = 0xe1d0eeec;
138135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment.Place(&section2).Place(&section1);
138235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
138335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  SegmentLoadCommand segment_command;
138435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment_command
138535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Header("head", segment, 0x92c9568c, 0xa89f2627, 0x4dc7a1e2)
138635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .AppendSectionEntry("mandarin", "kishu", 12, 0x8cd4604bU, section1)
138735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .AppendSectionEntry("bergamot", "cara cara", 12, 0x98746efaU, section2);
138835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
138935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadCommands commands;
139035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  commands.Place(&segment_command);
139135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
139235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
139335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file.Header(&commands).Place(&segment);
139435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
139535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFile(&file, true, CPU_TYPE_ANY, 0);
139635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
139735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Segment actual_segment;
139835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_CALL(load_command_handler, SegmentCommand(_))
139935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .WillOnce(DoAll(SaveArg<0>(&actual_segment),
140035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                      Return(true)));
140135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_TRUE(reader.WalkLoadCommands(&load_command_handler));
140235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
140335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  {
140435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    InSequence s;
140535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    ByteBuffer contents1;
140635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    contents1.start = file_bytes + section1.start().Value();
140735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    contents1.end = contents1.start + section1.final_size().Value();
140835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    EXPECT_EQ("buddha's hand",
140935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek              string(reinterpret_cast<const char *>(contents1.start),
141035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                     contents1.Size()));
141135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    EXPECT_CALL(section_handler,
141235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                HandleSection(MatchSection(true, "mandarin", "kishu",
141335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                                           section1.address().Value(), 12,
141435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                                           0x8cd4604bU, contents1)))
141535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .WillOnce(Return(true));
141635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
141735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    ByteBuffer contents2;
141835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    contents2.start = file_bytes + section2.start().Value();
141935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    contents2.end = contents2.start + section2.final_size().Value();
142035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    EXPECT_EQ("kumquat",
142135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek              string(reinterpret_cast<const char *>(contents2.start),
142235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                     contents2.Size()));
142335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    EXPECT_CALL(section_handler,
142435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                HandleSection(MatchSection(true, "bergamot", "cara cara",
142535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                                           section2.address().Value(), 12,
142635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                                           0x98746efaU, contents2)))
142735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .WillOnce(Return(true));
142835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  }
142935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
143035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_TRUE(reader.WalkSegmentSections(actual_segment, &section_handler));
143135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
143235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
143335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(LoadCommand, MisplacedSectionBefore) {
143435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kLittleEndian, 64);
143535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
143635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // The segment.
143735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadedSection segment;
143835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment.address() = 0x696d83cc;
143935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment.Append(10, '0');
144035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
144135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // The contents of the following sections don't matter, because
144235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // we're not really going to Place them in segment; we're just going
144335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // to set all their labels by hand to get the (impossible)
144435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // configurations we want.
144535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
144635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // A section whose starting offset is before that of its section.
144735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadedSection before;
144835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  before.Append(10, '1');
144935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  before.start()   = segment.start() - 1;
145035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  before.address() = segment.address() - 1;
145135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  before.final_size() = before.Size();
145235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
145335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  SegmentLoadCommand command;
145435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  command
145535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    .Header("segment", segment, 0x173baa29, 0x8407275d, 0xed8f7057)
145635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    .AppendSectionEntry("before",     "segment", 0, 0x686c6921, before);
145735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
145835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadCommands commands;
145935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  commands.Place(&command);
146035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
146135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
146235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file.Header(&commands).Place(&segment);
146335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
146435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFile(&file, true, CPU_TYPE_ANY, 0);
146535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
146635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Segment actual_segment;
146735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_TRUE(reader.FindSegment("segment", &actual_segment));
146835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
146935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_CALL(reporter, MisplacedSectionData("before", "segment"))
147035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    .WillOnce(Return());
147135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_FALSE(reader.WalkSegmentSections(actual_segment, &section_handler));
147235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
147335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
147435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(LoadCommand, MisplacedSectionAfter) {
147535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kLittleEndian, 64);
147635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
147735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // The segment.
147835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadedSection segment;
147935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment.address() = 0x696d83cc;
148035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment.Append(10, '0');
148135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
148235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // The contents of the following sections don't matter, because
148335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // we're not really going to Place them in segment; we're just going
148435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // to set all their labels by hand to get the (impossible)
148535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // configurations we want.
148635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
148735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // A section whose starting offset is after the end of its section.
148835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadedSection after;
148935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  after.Append(10, '2');
149035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  after.start()    = segment.start() + 11;
149135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  after.address()   = segment.address() + 11;
149235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  after.final_size() = after.Size();
149335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
149435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  SegmentLoadCommand command;
149535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  command
149635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    .Header("segment", segment, 0x173baa29, 0x8407275d, 0xed8f7057)
149735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    .AppendSectionEntry("after",      "segment", 0, 0x2ee50124, after);
149835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
149935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadCommands commands;
150035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  commands.Place(&command);
150135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
150235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
150335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file.Header(&commands).Place(&segment);
150435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
150535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFile(&file, true, CPU_TYPE_ANY, 0);
150635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
150735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Segment actual_segment;
150835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_TRUE(reader.FindSegment("segment", &actual_segment));
150935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
151035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_CALL(reporter, MisplacedSectionData("after", "segment"))
151135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    .WillOnce(Return());
151235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_FALSE(reader.WalkSegmentSections(actual_segment, &section_handler));
151335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
151435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
151535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(LoadCommand, MisplacedSectionTooBig) {
151635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kLittleEndian, 64);
151735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
151835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // The segment.
151935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadedSection segment;
152035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment.address() = 0x696d83cc;
152135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment.Append(10, '0');
152235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
152335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // The contents of the following sections don't matter, because
152435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // we're not really going to Place them in segment; we're just going
152535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // to set all their labels by hand to get the (impossible)
152635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // configurations we want.
152735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
152835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // A section that extends beyond the end of its section.
152935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadedSection too_big;
153035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  too_big.Append(10, '3');
153135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  too_big.start()   = segment.start() + 1;
153235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  too_big.address() = segment.address() + 1;
153335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  too_big.final_size() = too_big.Size();
153435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
153535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  SegmentLoadCommand command;
153635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  command
153735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    .Header("segment", segment, 0x173baa29, 0x8407275d, 0xed8f7057)
153835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    .AppendSectionEntry("too big",    "segment", 0, 0x8b53ae5c, too_big);
153935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
154035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadCommands commands;
154135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  commands.Place(&command);
154235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
154335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
154435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file.Header(&commands).Place(&segment);
154535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
154635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFile(&file, true, CPU_TYPE_ANY, 0);
154735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
154835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Segment actual_segment;
154935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_TRUE(reader.FindSegment("segment", &actual_segment));
155035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
155135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_CALL(reporter, MisplacedSectionData("too big", "segment"))
155235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    .WillOnce(Return());
155335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_FALSE(reader.WalkSegmentSections(actual_segment, &section_handler));
155435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
155535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
155635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
155735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// The segments in a .dSYM bundle's Mach-O file have their file offset
155835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// and size set to zero, but the sections don't.  The reader shouldn't
155935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// report an error in this case.
156035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(LoadCommand, ZappedSegment) {
156135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kBigEndian, 32);
156235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
156335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // The segment.
156435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadedSection segment;
156535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment.address() = 0x696d83cc;
156635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment.start() = 0;
156735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment.final_size() = 0;
156835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
156935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // The section.
157035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadedSection section;
157135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  section.address() = segment.address();
157235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  section.start() = 0;
157335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  section.final_size() = 1000;          // extends beyond its segment
157435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
157535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  SegmentLoadCommand command;
157635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  command
157735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    .Header("zapped", segment, 0x0861a5cb, 0x68ccff67, 0x0b66255c)
157835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    .AppendSectionEntry("twitching", "zapped", 0, 0x93b3bd42, section);
157935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
158035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadCommands commands;
158135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  commands.Place(&command);
158235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
158335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
158435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file.Header(&commands);
158535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
158635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFile(&file, true, CPU_TYPE_ANY, 0);
158735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
158835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Segment actual_segment;
158935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_TRUE(reader.FindSegment("zapped", &actual_segment));
159035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
159135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ByteBuffer zapped_extent(NULL, 0);
159235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_CALL(section_handler,
159335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek              HandleSection(MatchSection(false, "twitching", "zapped",
159435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                                         0x696d83cc, 0, 0x93b3bd42,
159535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                                         zapped_extent)))
159635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    .WillOnce(Return(true));
159735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
159835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_TRUE(reader.WalkSegmentSections(actual_segment, &section_handler));
159935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
160035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
160135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(LoadCommand, MapSegmentSections) {
160235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kLittleEndian, 32);
160335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
160435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Create some sections with some data.
160535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadedSection section1, section2, section3, section4;
160635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  section1.Append("buddha's hand");
160735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  section2.start() = 0;                 // Section 2 is an S_ZEROFILL section.
160835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  section2.final_size() = 0;
160935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  section3.Append("shasta gold");
161035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  section4.Append("satsuma");
161135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
161235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Create two segments to hold them.
161335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadedSection segment1, segment2;
161435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment1.address() = 0x13e6c8a9;
161535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment1.Place(&section3).Place(&section1);
161635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment2.set_word_size(64);
161735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment2.address() = 0x04d462e2;
161835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment2.Place(&section4);
161935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  section2.address() = segment2.address() + segment2.Size();
162035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
162135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  SegmentLoadCommand segment_command1, segment_command2;
162235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment_command1
162335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Header("head", segment1, 0x67d955a6, 0x7a61c13e, 0xe3e50c64)
162435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .AppendSectionEntry("mandarin", "head", 12, 0x5bb565d7, section1)
162535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .AppendSectionEntry("bergamot", "head", 12, 0x8620de73, section3);
162635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment_command2.set_word_size(64);
162735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment_command2
162835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Header("thorax", segment2, 0x7aab2419, 0xe908007f, 0x17961d33)
162935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .AppendSectionEntry("sixteenprecisely", "thorax",
163035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                          12, S_ZEROFILL, section2)
163135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .AppendSectionEntry("cara cara", "thorax", 12, 0xb6c5dd8a, section4);
163235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
163335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadCommands commands;
163435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  commands.Place(&segment_command1).Place(&segment_command2);
163535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
163635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
163735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file.Header(&commands).Place(&segment1).Place(&segment2);
163835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
163935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFile(&file, true, CPU_TYPE_ANY, 0);
164035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
164135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Segment segment;
164235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  SectionMap section_map;
164335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
164435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_FALSE(reader.FindSegment("smoot", &segment));
164535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
164635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ASSERT_TRUE(reader.FindSegment("thorax", &segment));
164735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ASSERT_TRUE(reader.MapSegmentSections(segment, &section_map));
164835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
164935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_FALSE(section_map.find("sixteenpreciselyandthensome")
165035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek               != section_map.end());
165135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_FALSE(section_map.find("mandarin") != section_map.end());
165235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ASSERT_TRUE(section_map.find("cara cara") != section_map.end());
165335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_THAT(section_map["cara cara"],
165435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek              MatchSection(true, "cara cara", "thorax", 0x04d462e2));
165535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ASSERT_TRUE(section_map.find("sixteenprecisely")
165635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek              != section_map.end());
165735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ByteBuffer sixteenprecisely_contents(NULL, 0);
165835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_THAT(section_map["sixteenprecisely"],
165935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek              MatchSection(true, "sixteenprecisely", "thorax",
166035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                           0x04d462e2 + 7, 12, S_ZEROFILL,
166135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                           sixteenprecisely_contents));
166235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
166335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ASSERT_TRUE(reader.FindSegment("head", &segment));
166435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ASSERT_TRUE(reader.MapSegmentSections(segment, &section_map));
166535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
166635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ASSERT_TRUE(section_map.find("mandarin") != section_map.end());
166735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_THAT(section_map["mandarin"],
166835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek              MatchSection(false, "mandarin", "head", 0x13e6c8a9 + 11));
166935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ASSERT_TRUE(section_map.find("bergamot") != section_map.end());
167035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_THAT(section_map["bergamot"],
167135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek              MatchSection(false, "bergamot", "head", 0x13e6c8a9));
167235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
167335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
167435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(LoadCommand, FindSegment) {
167535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kBigEndian, 32);
167635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
167735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadedSection segment1, segment2, segment3;
167835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment1.address() = 0xb8ae5752;
167935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment1.Append("Some contents!");
168035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment2.address() = 0xd6b0ce83;
168135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment2.Append("Different stuff.");
168235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment3.address() = 0x7374fd2a;
168335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  segment3.Append("Further materials.");
168435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
168535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  SegmentLoadCommand cmd1, cmd2, cmd3;
168635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  cmd1.Header("first",  segment1, 0xfadb6932, 0x175bf529, 0x0de790ad);
168735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  cmd2.Header("second", segment2, 0xeef716e0, 0xe103a9d7, 0x7d38a8ef);
168835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  cmd3.Header("third",  segment3, 0xe172b39e, 0x86012f07, 0x080ac94d);
168935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
169035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadCommands commands;
169135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  commands.Place(&cmd1).Place(&cmd2).Place(&cmd3);
169235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
169335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
169435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file.Header(&commands).Place(&segment1).Place(&segment2).Place(&segment3);
169535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
169635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFile(&file, true, CPU_TYPE_ANY, 0);
169735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
169835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  Segment actual_segment;
169935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
170035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_FALSE(reader.FindSegment("murphy", &actual_segment));
170135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
170235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_TRUE(reader.FindSegment("second", &actual_segment));
170335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(0xd6b0ce83, actual_segment.vmaddr);
170435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
170535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
170635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
170735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// Symtab tests.
170835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
170935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// A StringAssembler is a class for generating .stabstr sections to present
171035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// as input to the STABS parser.
171135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekclass StringAssembler: public SizedSection {
171235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek public:
171335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Add the string S to this StringAssembler, and return the string's
171435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // offset within this compilation unit's strings.
171535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  size_t Add(const string &s) {
171635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    size_t offset = Size();
171735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    AppendCString(s);
171835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    return offset;
171935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  }
172035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek};
172135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
172235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// A SymbolAssembler is a class for generating .stab sections to present as
172335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek// test input for the STABS parser.
172435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekclass SymbolAssembler: public SizedSection {
172535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek public:
172635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Create a SymbolAssembler that uses StringAssembler for its strings.
172735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  explicit SymbolAssembler(StringAssembler *string_assembler)
172835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      : string_assembler_(string_assembler),
172935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek        entry_count_(0) { }
173035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
173135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Append a STAB entry to the end of this section with the given
173235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // characteristics. NAME is the offset of this entry's name string within
173335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // its compilation unit's portion of the .stabstr section; this can be a
173435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // value generated by a StringAssembler. Return a reference to this
173535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // SymbolAssembler.
173635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  SymbolAssembler &Symbol(uint8_t type, uint8_t other, Label descriptor,
173735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                          Label value, Label name) {
173835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    D32(name);
173935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    D8(type);
174035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    D8(other);
174135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    D16(descriptor);
174235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    Append(endianness(), word_size_ / 8, value);
174335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    entry_count_++;
174435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    return *this;
174535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  }
174635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
174735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // As above, but automatically add NAME to our StringAssembler.
174835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  SymbolAssembler &Symbol(uint8_t type, uint8_t other, Label descriptor,
174935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                       Label value, const string &name) {
175035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek    return Symbol(type, other, descriptor, value, string_assembler_->Add(name));
175135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  }
175235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
175335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek private:
175435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // The strings for our STABS entries.
175535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  StringAssembler *string_assembler_;
175635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
175735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // The number of entries in this compilation unit so far.
175835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  size_t entry_count_;
175935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek};
176035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
176135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekclass Symtab: public ReaderFixture, public Test { };
176235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
176335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(Symtab, Symtab32) {
176435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kLittleEndian, 32);
176535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
176635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  StringAssembler strings;
176735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  SymbolAssembler symbols(&strings);
176835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  symbols
176935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Symbol(0x52, 0x7c, 0x3470, 0x9bb02e7c, "hrududu")
177035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Symbol(0x50, 0x90, 0x7520, 0x1122525d, "Frith");
177135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
177235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  SizedSection symtab_command;
177335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  symtab_command
177435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(LC_SYMTAB)                    // command
177535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(symtab_command.final_size())  // size
177635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(symbols.start())              // file offset of symbols
177735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(2)                            // symbol count
177835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(strings.start())              // file offset of strings
177935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(strings.final_size());        // strings size
178035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
178135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadCommands load_commands;
178235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  load_commands.Place(&symtab_command);
178335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
178435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
178535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file.Header(&load_commands).Place(&symbols).Place(&strings);
178635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
178735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFile(&file, true, CPU_TYPE_ANY, 0);
178835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
178935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ByteBuffer symbols_found, strings_found;
179035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_CALL(load_command_handler, SymtabCommand(_, _))
179135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .WillOnce(DoAll(SaveArg<0>(&symbols_found),
179235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                      SaveArg<1>(&strings_found),
179335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                      Return(true)));
179435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_TRUE(reader.WalkLoadCommands(&load_command_handler));
179535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
179635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(24U, symbols_found.Size());
179735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(14U, strings_found.Size());
179835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
179935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
180035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(Symtab, Symtab64) {
180135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kBigEndian, 64);
180235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
180335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  StringAssembler strings;
180435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  SymbolAssembler symbols(&strings);
180535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  symbols
180635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Symbol(0xa7, 0xaf, 0x03af, 0x42f3072c74335181ULL, "foo")
180735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Symbol(0xb0, 0x9a, 0x2aa7, 0x2e2d349b3d5744a0ULL, "bar");
180835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
180935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  SizedSection symtab_command;
181035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  symtab_command
181135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(LC_SYMTAB)                    // command
181235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(symtab_command.final_size())  // size
181335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(symbols.start())              // file offset of symbols
181435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(2)                            // symbol count
181535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(strings.start())              // file offset of strings
181635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(strings.final_size());        // strings size
181735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
181835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadCommands load_commands;
181935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  load_commands.Place(&symtab_command);
182035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
182135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
182235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file.Header(&load_commands).Place(&symbols).Place(&strings);
182335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
182435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFile(&file, true, CPU_TYPE_ANY, 0);
182535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
182635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ByteBuffer symbols_found, strings_found;
182735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_CALL(load_command_handler, SymtabCommand(_, _))
182835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .WillOnce(DoAll(SaveArg<0>(&symbols_found),
182935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                      SaveArg<1>(&strings_found),
183035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek                      Return(true)));
183135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_TRUE(reader.WalkLoadCommands(&load_command_handler));
183235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
183335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(32U, symbols_found.Size());
183435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_EQ(8U,  strings_found.Size());
183535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
183635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
183735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(Symtab, SymtabMisplacedSymbols) {
183835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kBigEndian, 32);
183935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
184035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  StringAssembler strings;
184135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  SymbolAssembler symbols(&strings);
184235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  symbols
184335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Symbol(0xa7, 0xaf, 0x03af, 0x42f3072c74335181ULL, "foo")
184435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Symbol(0xb0, 0x9a, 0x2aa7, 0x2e2d349b3d5744a0ULL, "bar");
184535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
184635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  SizedSection symtab_command;
184735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  symtab_command
184835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(LC_SYMTAB)                    // command
184935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(symtab_command.final_size())  // size
185035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(symbols.start())              // file offset of symbols
185135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(3)                            // symbol count (too many)
185235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(strings.start())              // file offset of strings
185335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(strings.final_size());        // strings size
185435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
185535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadCommands load_commands;
185635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  load_commands.Place(&symtab_command);
185735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
185835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
185935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Put symbols at end, so the excessive length will be noticed.
186035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file.Header(&load_commands).Place(&strings).Place(&symbols);
186135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
186235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFile(&file, true, CPU_TYPE_ANY, 0);
186335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
186435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_CALL(reporter, MisplacedSymbolTable()).Times(1);
186535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_FALSE(reader.WalkLoadCommands(&load_command_handler));
186635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
186735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
186835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekTEST_F(Symtab, SymtabMisplacedStrings) {
186935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  WithConfiguration config(kLittleEndian, 32);
187035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
187135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  StringAssembler strings;
187235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  SymbolAssembler symbols(&strings);
187335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  symbols
187435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Symbol(0xa7, 0xaf, 0x03af, 0x42f3072c74335181ULL, "foo")
187535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .Symbol(0xb0, 0x9a, 0x2aa7, 0x2e2d349b3d5744a0ULL, "bar");
187635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
187735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  SizedSection symtab_command;
187835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  symtab_command
187935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(LC_SYMTAB)                    // command
188035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(symtab_command.final_size())  // size
188135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(symbols.start())              // file offset of symbols
188235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(2)                            // symbol count
188335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(strings.start())              // file offset of strings
188435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek      .D32(strings.final_size() + 1);    // strings size (too long)
188535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
188635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  LoadCommands load_commands;
188735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  load_commands.Place(&symtab_command);
188835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
188935c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  MachOFile file;
189035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  // Put strings at end, so the excessive length will be noticed.
189135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  file.Header(&load_commands).Place(&symbols).Place(&strings);
189235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
189335c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  ReadFile(&file, true, CPU_TYPE_ANY, 0);
189435c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
189535c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_CALL(reporter, MisplacedSymbolTable()).Times(1);
189635c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek  EXPECT_FALSE(reader.WalkLoadCommands(&load_command_handler));
189735c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek}
189835c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarek
1899