// Copyright (c) 2011 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Original author: Ted Mielczarek <ted.mielczarek@gmail.com>

// dump_symbols_unittest.cc:
// Unittests for google_breakpad::DumpSymbols

#include <elf.h>
#include <link.h>
#include <stdio.h>

#include <sstream>
#include <vector>

#include "breakpad_googletest_includes.h"
#include "common/linux/elf_gnu_compat.h"
#include "common/linux/elfutils.h"
#include "common/linux/dump_symbols.h"
#include "common/linux/synth_elf.h"
#include "common/module.h"
#include "common/using_std_string.h"

namespace google_breakpad {

bool ReadSymbolDataInternal(const uint8_t* obj_file,
                            const string& obj_filename,
                            const std::vector<string>& debug_dir,
                            const DumpOptions& options,
                            Module** module);

using google_breakpad::synth_elf::ELF;
using google_breakpad::synth_elf::Notes;
using google_breakpad::synth_elf::StringTable;
using google_breakpad::synth_elf::SymbolTable;
using google_breakpad::test_assembler::kLittleEndian;
using google_breakpad::test_assembler::Section;
using std::stringstream;
using std::vector;
using ::testing::Test;
using ::testing::Types;

template<typename ElfClass>
class DumpSymbols : public Test {
 public:
  void GetElfContents(ELF& elf) {
    string contents;
    ASSERT_TRUE(elf.GetContents(&contents));
    ASSERT_LT(0U, contents.size());

    elfdata_v.clear();
    elfdata_v.insert(elfdata_v.begin(), contents.begin(), contents.end());
    elfdata = &elfdata_v[0];
  }

  vector<uint8_t> elfdata_v;
  uint8_t* elfdata;
};

typedef Types<ElfClass32, ElfClass64> ElfClasses;

TYPED_TEST_CASE(DumpSymbols, ElfClasses);

TYPED_TEST(DumpSymbols, Invalid) {
  Elf32_Ehdr header;
  memset(&header, 0, sizeof(header));
  Module* module;
  DumpOptions options(ALL_SYMBOL_DATA, true);
  EXPECT_FALSE(ReadSymbolDataInternal(reinterpret_cast<uint8_t*>(&header),
                                      "foo",
                                      vector<string>(),
                                      options,
                                      &module));
}

TYPED_TEST(DumpSymbols, SimplePublic) {
  ELF elf(TypeParam::kMachine, TypeParam::kClass, kLittleEndian);
  // Zero out text section for simplicity.
  Section text(kLittleEndian);
  text.Append(4096, 0);
  elf.AddSection(".text", text, SHT_PROGBITS);

  // Add a public symbol.
  StringTable table(kLittleEndian);
  SymbolTable syms(kLittleEndian, TypeParam::kAddrSize, table);
  syms.AddSymbol("superfunc",
                   (typename TypeParam::Addr)0x1000,
                   (typename TypeParam::Addr)0x10,
                 // ELF32_ST_INFO works for 32-or 64-bit.
                 ELF32_ST_INFO(STB_GLOBAL, STT_FUNC),
                 SHN_UNDEF + 1);
  int index = elf.AddSection(".dynstr", table, SHT_STRTAB);
  elf.AddSection(".dynsym", syms,
                 SHT_DYNSYM,          // type
                 SHF_ALLOC,           // flags
                 0,                   // addr
                 index,               // link
                 sizeof(typename TypeParam::Sym));  // entsize

  elf.Finish();
  this->GetElfContents(elf);

  Module* module;
  DumpOptions options(ALL_SYMBOL_DATA, true);
  EXPECT_TRUE(ReadSymbolDataInternal(this->elfdata,
                                     "foo",
                                     vector<string>(),
                                     options,
                                     &module));

  stringstream s;
  module->Write(s, ALL_SYMBOL_DATA);
  const string expected =
    string("MODULE Linux ") + TypeParam::kMachineName
    + " 000000000000000000000000000000000 foo\n"
    "INFO CODE_ID 00000000000000000000000000000000\n"
    "PUBLIC 1000 0 superfunc\n";
  EXPECT_EQ(expected, s.str());
  delete module;
}

TYPED_TEST(DumpSymbols, SimpleBuildID) {
  ELF elf(TypeParam::kMachine, TypeParam::kClass, kLittleEndian);
  // Zero out text section for simplicity.
  Section text(kLittleEndian);
  text.Append(4096, 0);
  elf.AddSection(".text", text, SHT_PROGBITS);

  // Add a Build ID
  const uint8_t kExpectedIdentifierBytes[] =
    {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
     0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
     0x10, 0x11, 0x12, 0x13};
  Notes notes(kLittleEndian);
  notes.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifierBytes,
                sizeof(kExpectedIdentifierBytes));
  elf.AddSection(".note.gnu.build-id", notes, SHT_NOTE);

  // Add a public symbol.
  StringTable table(kLittleEndian);
  SymbolTable syms(kLittleEndian, TypeParam::kAddrSize, table);
  syms.AddSymbol("superfunc",
                   (typename TypeParam::Addr)0x1000,
                   (typename TypeParam::Addr)0x10,
                 // ELF32_ST_INFO works for 32-or 64-bit.
                 ELF32_ST_INFO(STB_GLOBAL, STT_FUNC),
                 SHN_UNDEF + 1);
  int index = elf.AddSection(".dynstr", table, SHT_STRTAB);
  elf.AddSection(".dynsym", syms,
                 SHT_DYNSYM,          // type
                 SHF_ALLOC,           // flags
                 0,                   // addr
                 index,               // link
                 sizeof(typename TypeParam::Sym));  // entsize

  elf.Finish();
  this->GetElfContents(elf);

  Module* module;
  DumpOptions options(ALL_SYMBOL_DATA, true);
  EXPECT_TRUE(ReadSymbolDataInternal(this->elfdata,
                                     "foo",
                                     vector<string>(),
                                     options,
                                     &module));

  stringstream s;
  module->Write(s, ALL_SYMBOL_DATA);
  const string expected =
    string("MODULE Linux ") + TypeParam::kMachineName
    + " 030201000504070608090A0B0C0D0E0F0 foo\n"
    "INFO CODE_ID 000102030405060708090A0B0C0D0E0F10111213\n"
    "PUBLIC 1000 0 superfunc\n";
  EXPECT_EQ(expected, s.str());
  delete module;
}

}  // namespace google_breakpad
