Commit cc0afbf7 authored by Thomas Anderson's avatar Thomas Anderson Committed by Commit Bot

Revert "Add utils to read elf binary and get Build id"

This reverts commit 61248f1a.

Reason for revert: Suspected breaking component builds (bug 837817)

Original change's description:
> Add utils to read elf binary and get Build id
> 
> Adds code to parse elf binary to get build id from
> .note.gnu.build-id section. The build ID is needed to symbolize
> heap dumps from the users.
> 
> BUG=734705
> 
> Change-Id: If4365e232c060ba96071ba1e1c43618f9807e39c
> Reviewed-on: https://chromium-review.googlesource.com/1028995
> Commit-Queue: Siddhartha S <ssid@chromium.org>
> Reviewed-by: Lei Zhang <thestig@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#554304}

TBR=thestig@chromium.org,ssid@chromium.org

Change-Id: If512434b55bcc912990e3997a86f6f93722b15fb
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 734705
Reviewed-on: https://chromium-review.googlesource.com/1033795Reviewed-by: default avatarThomas Anderson <thomasanderson@chromium.org>
Commit-Queue: Thomas Anderson <thomasanderson@chromium.org>
Cr-Commit-Position: refs/heads/master@{#554532}
parent 697a2e68
......@@ -1164,11 +1164,7 @@ jumbo_component("base") {
]
if (is_linux) {
sources += [
"base_paths_posix.cc",
"debug/elf_reader_linux.cc",
"debug/elf_reader_linux.h",
]
sources += [ "base_paths_posix.cc" ]
}
}
......@@ -1268,8 +1264,6 @@ jumbo_component("base") {
# Android uses some Linux sources, put those back.
set_sources_assignment_filter([])
sources += [
"debug/elf_reader_linux.cc",
"debug/elf_reader_linux.h",
"debug/proc_maps_linux.cc",
"debug/proc_maps_linux.h",
"files/file_path_watcher_linux.cc",
......@@ -2143,7 +2137,6 @@ test("base_unittests") {
"debug/alias_unittest.cc",
"debug/crash_logging_unittest.cc",
"debug/debugger_unittest.cc",
"debug/elf_reader_linux_unittest.cc",
"debug/leak_tracker_unittest.cc",
"debug/proc_maps_linux_unittest.cc",
"debug/stack_trace_unittest.cc",
......@@ -2585,7 +2578,6 @@ test("base_unittests") {
deps += [ "//testing/android/native_test:native_test_native_code" ]
set_sources_assignment_filter([])
sources += [
"debug/elf_reader_linux_unittest.cc",
"debug/proc_maps_linux_unittest.cc",
"trace_event/trace_event_android_unittest.cc",
]
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/debug/elf_reader_linux.h"
#include <arpa/inet.h>
#include <elf.h>
#include <vector>
#include "base/bits.h"
#include "base/containers/span.h"
#include "base/sha1.h"
#include "base/strings/stringprintf.h"
extern char __executable_start;
namespace base {
namespace debug {
namespace {
#if __SIZEOF_POINTER__ == 4
using Ehdr = Elf32_Ehdr;
using Half = Elf32_Half;
using Nhdr = Elf32_Nhdr;
using Phdr = Elf32_Phdr;
#else
using Ehdr = Elf64_Ehdr;
using Half = Elf64_Half;
using Nhdr = Elf64_Nhdr;
using Phdr = Elf64_Phdr;
#endif
using ElfSegment = span<const char>;
Optional<std::string> ElfSegmentBuildIDNoteAsString(const ElfSegment& segment) {
const void* section_end = segment.data() + segment.size_bytes();
const Nhdr* note_header = reinterpret_cast<const Nhdr*>(segment.data());
while (note_header < section_end) {
if (note_header->n_type == NT_GNU_BUILD_ID)
break;
note_header = reinterpret_cast<const Nhdr*>(
reinterpret_cast<const char*>(note_header) + sizeof(Nhdr) +
bits::Align(note_header->n_namesz, 4) +
bits::Align(note_header->n_descsz, 4));
}
if (note_header >= section_end || note_header->n_descsz != kSHA1Length)
return nullopt;
const uint8_t* guid = reinterpret_cast<const uint8_t*>(note_header) +
sizeof(Nhdr) + bits::Align(note_header->n_namesz, 4);
uint32_t dword = htonl(*reinterpret_cast<const int32_t*>(guid));
uint16_t word1 = htons(*reinterpret_cast<const int16_t*>(guid + 4));
uint16_t word2 = htons(*reinterpret_cast<const int16_t*>(guid + 6));
std::string identifier;
identifier.reserve(kSHA1Length * 2); // as hex string
SStringPrintf(&identifier, "%08X%04X%04X", dword, word1, word2);
for (size_t i = 8; i < note_header->n_descsz; ++i)
StringAppendF(&identifier, "%02X", guid[i]);
return identifier;
}
std::vector<ElfSegment> FindElfSegments(const char* elf_base,
uint32_t segment_type) {
if (strncmp(static_cast<const char*>(elf_base), ELFMAG, SELFMAG) != 0)
return std::vector<ElfSegment>();
const Ehdr* elf_header = reinterpret_cast<const Ehdr*>(elf_base);
const Phdr* phdrs =
reinterpret_cast<const Phdr*>(elf_base + elf_header->e_phoff);
std::vector<ElfSegment> segments;
for (Half i = 0; i < elf_header->e_phnum; ++i) {
if (phdrs[i].p_type == segment_type)
segments.push_back({elf_base + phdrs[i].p_offset, phdrs[i].p_filesz});
}
return segments;
}
} // namespace
Optional<std::string> ReadElfBuildId() {
// Elf program headers can have multiple PT_NOTE arrays.
std::vector<ElfSegment> segs = FindElfSegments(&__executable_start, PT_NOTE);
if (segs.empty())
return nullopt;
Optional<std::string> id;
for (const ElfSegment& seg : segs) {
id = ElfSegmentBuildIDNoteAsString(seg);
if (id)
return id;
}
return nullopt;
}
} // namespace debug
} // namespace base
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_DEBUG_ELF_READER_LINUX_H_
#define BASE_DEBUG_ELF_READER_LINUX_H_
#include <string>
#include "base/base_export.h"
#include "base/optional.h"
namespace base {
namespace debug {
// Returns the ELF section .note.gnu.build-id from current executable file, if
// present.
Optional<std::string> BASE_EXPORT ReadElfBuildId();
} // namespace debug
} // namespace base
#endif // BASE_DEBUG_ELF_READER_LINUX_H_
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/debug/elf_reader_linux.h"
#include "base/strings/string_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace base {
namespace debug {
// The linker flag --build-id is passed only on official builds. Clang does not
// enable it by default and we do not have build id section in non-official
// builds.
#if defined(OFFICIAL_BUILD)
TEST(ElfReaderTest, ReadElfBuildId) {
Optional<std::string> build_id = ReadElfBuildId();
ASSERT_TRUE(build_id);
const size_t kGuidBytes = 20;
EXPECT_EQ(2 * kGuidBytes, build_id.value().size());
for (char c : *build_id) {
EXPECT_TRUE(IsHexDigit(c));
EXPECT_FALSE(IsAsciiLower(c));
}
}
#endif
} // namespace debug
} // namespace base
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment