// Copyright (c) 2007, 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.

// file_id.cc: Return a unique identifier for a file
//
// See file_id.h for documentation
//
// Author: Alfred Peng

#include <elf.h>
#include <fcntl.h>
#include <gelf.h>
#include <sys/mman.h>
#include <sys/ksyms.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include <cassert>
#include <cstdio>

#include "common/md5.h"
#include "common/solaris/file_id.h"
#include "common/solaris/message_output.h"
#include "google_breakpad/common/minidump_format.h"

namespace google_breakpad {

class AutoElfEnder {
 public:
  AutoElfEnder(Elf *elf) : elf_(elf) {}
  ~AutoElfEnder() { if (elf_) elf_end(elf_); }
 private:
  Elf *elf_;
};

// Find the text section in elf object file.
// Return the section start address and the size.
static bool FindElfTextSection(int fd, const void *elf_base,
                               const void **text_start,
                               int *text_size) {
  assert(text_start);
  assert(text_size);

  *text_start = NULL;
  *text_size = 0;

  if (elf_version(EV_CURRENT) == EV_NONE) {
    print_message2(2, "elf_version() failed: %s\n", elf_errmsg(0));
    return false;
  }

  GElf_Ehdr elf_header;
  lseek(fd, 0L, 0);
  Elf *elf = elf_begin(fd, ELF_C_READ, NULL);
  AutoElfEnder elfEnder(elf);

  if (gelf_getehdr(elf, &elf_header) == (GElf_Ehdr *)NULL) {
    print_message2(2, "failed to read elf header: %s\n", elf_errmsg(-1));
    return false;
  }

  if (elf_header.e_ident[EI_MAG0] != ELFMAG0 ||
      elf_header.e_ident[EI_MAG1] != ELFMAG1 ||
      elf_header.e_ident[EI_MAG2] != ELFMAG2 ||
      elf_header.e_ident[EI_MAG3] != ELFMAG3) {
    print_message1(2, "header magic doesn't match\n");
    return false;
  }

  static const char kTextSectionName[] = ".text";
  const GElf_Shdr *text_section = NULL;
  Elf_Scn *scn = NULL;
  GElf_Shdr shdr;

  while ((scn = elf_nextscn(elf, scn)) != NULL) {
    if (gelf_getshdr(scn, &shdr) == (GElf_Shdr *)0) {
      print_message2(2, "failed to read section header: %s\n", elf_errmsg(0));
      return false;
    }

    if (shdr.sh_type == SHT_PROGBITS) {
      const char *section_name = elf_strptr(elf, elf_header.e_shstrndx,
                                            shdr.sh_name);
      if (!section_name) {
        print_message2(2, "Section name error: %s\n", elf_errmsg(-1));
        continue;
      }

      if (strcmp(section_name, kTextSectionName) == 0) {
        text_section = &shdr;
        break;
      }
    }
  }
  if (text_section != NULL && text_section->sh_size > 0) {
    *text_start = (char *)elf_base + text_section->sh_offset;
    *text_size = text_section->sh_size;
    return true;
  }

  return false;
}

FileID::FileID(const char *path) {
  strcpy(path_, path);
}

class AutoCloser {
 public:
  AutoCloser(int fd) : fd_(fd) {}
  ~AutoCloser() { if (fd_) close(fd_); }
 private:
  int fd_;
};

bool FileID::ElfFileIdentifier(unsigned char identifier[16]) {
  int fd = 0;
  if ((fd = open(path_, O_RDONLY)) < 0)
    return false;

  AutoCloser autocloser(fd);
  struct stat st;
  if (fstat(fd, &st) != 0 || st.st_size <= 0)
    return false;

  void *base = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
  if (base == MAP_FAILED)
    return false;

  bool success = false;
  const void *text_section = NULL;
  int text_size = 0;

  if (FindElfTextSection(fd, base, &text_section, &text_size)) {
    MD5Context md5;
    MD5Init(&md5);
    MD5Update(&md5, (const unsigned char *)text_section, text_size);
    MD5Final(identifier, &md5);
    success = true;
  }

  munmap((char *)base, st.st_size);
  return success;
}

// static
bool FileID::ConvertIdentifierToString(const unsigned char identifier[16],
                                       char *buffer, int buffer_length) {
  if (buffer_length < 34)
    return false;

  int buffer_idx = 0;
  for (int idx = 0; idx < 16; ++idx) {
    int hi = (identifier[idx] >> 4) & 0x0F;
    int lo = (identifier[idx]) & 0x0F;

    buffer[buffer_idx++] = (hi >= 10) ? 'A' + hi - 10 : '0' + hi;
    buffer[buffer_idx++] = (lo >= 10) ? 'A' + lo - 10 : '0' + lo;
  }

  // Add an extra "0" by the end.
  buffer[buffer_idx++] = '0';

  // NULL terminate
  buffer[buffer_idx] = 0;

  return true;
}

}  // namespace google_breakpad
