Commit 04ec9b02 authored by Siddhartha's avatar Siddhartha Committed by Commit Bot

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

This reverts commit cc0afbf7.

Reason for revert: Move the variable to test file and use it only on
official builds. Both Chromeos component and official build works.

Original change's description:
> 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/1033795
> Reviewed-by: Thomas Anderson <thomasanderson@chromium.org>
> Commit-Queue: Thomas Anderson <thomasanderson@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#554532}

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

Change-Id: Ie2fb8f7fe0759dc418a1bc4ffc57bdb4542ba606
Bug: 734705, 837817
Reviewed-on: https://chromium-review.googlesource.com/1033498
Commit-Queue: Siddhartha S <ssid@chromium.org>
Reviewed-by: default avatarSiddhartha S <ssid@chromium.org>
Cr-Commit-Position: refs/heads/master@{#554601}
parent a4021071
...@@ -1164,7 +1164,11 @@ jumbo_component("base") { ...@@ -1164,7 +1164,11 @@ jumbo_component("base") {
] ]
if (is_linux) { if (is_linux) {
sources += [ "base_paths_posix.cc" ] sources += [
"base_paths_posix.cc",
"debug/elf_reader_linux.cc",
"debug/elf_reader_linux.h",
]
} }
} }
...@@ -1264,6 +1268,8 @@ jumbo_component("base") { ...@@ -1264,6 +1268,8 @@ jumbo_component("base") {
# Android uses some Linux sources, put those back. # Android uses some Linux sources, put those back.
set_sources_assignment_filter([]) set_sources_assignment_filter([])
sources += [ sources += [
"debug/elf_reader_linux.cc",
"debug/elf_reader_linux.h",
"debug/proc_maps_linux.cc", "debug/proc_maps_linux.cc",
"debug/proc_maps_linux.h", "debug/proc_maps_linux.h",
"files/file_path_watcher_linux.cc", "files/file_path_watcher_linux.cc",
...@@ -2137,6 +2143,7 @@ test("base_unittests") { ...@@ -2137,6 +2143,7 @@ test("base_unittests") {
"debug/alias_unittest.cc", "debug/alias_unittest.cc",
"debug/crash_logging_unittest.cc", "debug/crash_logging_unittest.cc",
"debug/debugger_unittest.cc", "debug/debugger_unittest.cc",
"debug/elf_reader_linux_unittest.cc",
"debug/leak_tracker_unittest.cc", "debug/leak_tracker_unittest.cc",
"debug/proc_maps_linux_unittest.cc", "debug/proc_maps_linux_unittest.cc",
"debug/stack_trace_unittest.cc", "debug/stack_trace_unittest.cc",
...@@ -2578,6 +2585,7 @@ test("base_unittests") { ...@@ -2578,6 +2585,7 @@ test("base_unittests") {
deps += [ "//testing/android/native_test:native_test_native_code" ] deps += [ "//testing/android/native_test:native_test_native_code" ]
set_sources_assignment_filter([]) set_sources_assignment_filter([])
sources += [ sources += [
"debug/elf_reader_linux_unittest.cc",
"debug/proc_maps_linux_unittest.cc", "debug/proc_maps_linux_unittest.cc",
"trace_event/trace_event_android_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"
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 void* elf_mapped_base,
uint32_t segment_type) {
const char* elf_base = reinterpret_cast<const char*>(elf_mapped_base);
if (strncmp(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(const void* elf_base) {
// Elf program headers can have multiple PT_NOTE arrays.
std::vector<ElfSegment> segs = FindElfSegments(&elf_base, 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 the ELF file mapped at
// |elf_base|, if present. The caller must ensure that the file is fully mapped
// in memory.
Optional<std::string> BASE_EXPORT ReadElfBuildId(const void* elf_base);
} // 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"
extern char __executable_start;
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(&__executable_start);
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