diff options
author | simonb@chromium.org <simonb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-16 22:38:39 +0000 |
---|---|---|
committer | simonb@chromium.org <simonb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-16 22:38:39 +0000 |
commit | 4e7b4431ab30d9d291e7cb60b230b7f83affc7b0 (patch) | |
tree | c3985250385b2d3c39e8b67371ade1e55f16a782 /tools | |
parent | 78539dfc91cb59f079ac6ada3b80ac7e57fb0dc4 (diff) | |
download | chromium_src-4e7b4431ab30d9d291e7cb60b230b7f83affc7b0.zip chromium_src-4e7b4431ab30d9d291e7cb60b230b7f83affc7b0.tar.gz chromium_src-4e7b4431ab30d9d291e7cb60b230b7f83affc7b0.tar.bz2 |
Upgrade logging to resemble base/logging.h.
First phase of extending the relocation packer for arm64.
Upgrade logging to be streams-based. Add new unit tests to cover logging
and checking features. Mechanical changes to logging call sites.
Also correct a type promotion issue that causes incorrect DT_RELCOUNT
adjustments when the packer is compiled as a 32-bit Linux binary.
BUG=385553
Review URL: https://codereview.chromium.org/392653002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@283552 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'tools')
-rw-r--r-- | tools/relocation_packer/relocation_packer.gyp | 1 | ||||
-rw-r--r-- | tools/relocation_packer/src/debug.cc | 65 | ||||
-rw-r--r-- | tools/relocation_packer/src/debug.h | 150 | ||||
-rw-r--r-- | tools/relocation_packer/src/debug_unittest.cc | 123 | ||||
-rw-r--r-- | tools/relocation_packer/src/elf_file.cc | 188 | ||||
-rw-r--r-- | tools/relocation_packer/src/main.cc | 18 |
6 files changed, 360 insertions, 185 deletions
diff --git a/tools/relocation_packer/relocation_packer.gyp b/tools/relocation_packer/relocation_packer.gyp index f74a9e9..4642a27 100644 --- a/tools/relocation_packer/relocation_packer.gyp +++ b/tools/relocation_packer/relocation_packer.gyp @@ -46,6 +46,7 @@ '../..', ], 'sources': [ + 'src/debug_unittest.cc', 'src/elf_file_unittest.cc', 'src/leb128_unittest.cc', 'src/packer_unittest.cc', diff --git a/tools/relocation_packer/src/debug.cc b/tools/relocation_packer/src/debug.cc index b78e250..29d7ab0 100644 --- a/tools/relocation_packer/src/debug.cc +++ b/tools/relocation_packer/src/debug.cc @@ -2,43 +2,54 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <stdarg.h> -#include <stdio.h> - #include "debug.h" -namespace relocation_packer { +#include <stdlib.h> +#include <iostream> +#include <string> -Logger* Logger::instance_ = NULL; +namespace relocation_packer { -Logger* Logger::GetInstance() { - if (instance_ == NULL) - instance_ = new Logger; - return instance_; +// Construct a new message logger. Prints if level is less than or equal to +// the level set with SetVerbose() and predicate is true. +Logger::Logger(Severity severity, int level, bool predicate) { + severity_ = severity; + level_ = level; + predicate_ = predicate; } -void Logger::Log(const char* format, va_list args) { - vfprintf(stdout, format, args); +// On destruction, flush and print the strings accumulated. Abort if FATAL. +Logger::~Logger() { + if (predicate_) { + if (level_ <= max_level_) { + std::ostream* log = severity_ == INFO ? info_stream_ : error_stream_; + std::string tag; + switch (severity_) { + case INFO: tag = "INFO"; break; + case WARNING: tag = "WARNING"; break; + case ERROR: tag = "ERROR"; break; + case FATAL: tag = "FATAL"; break; + } + stream_.flush(); + *log << tag << ": " << stream_.str() << std::endl; + } + if (severity_ == FATAL) + abort(); + } } -void Logger::Log(const char* format, ...) { - va_list args; - va_start(args, format); - GetInstance()->Log(format, args); - va_end(args); +// Reset to initial state. +void Logger::Reset() { + max_level_ = -1; + info_stream_ = &std::cout; + error_stream_ = &std::cerr; } -void Logger::VLog(const char* format, ...) { - if (GetInstance()->is_verbose_) { - va_list args; - va_start(args, format); - GetInstance()->Log(format, args); - va_end(args); - } -} +// Verbosity. Not thread-safe. +int Logger::max_level_ = -1; -void Logger::SetVerbose(bool flag) { - GetInstance()->is_verbose_ = flag; -} +// Logging streams. Not thread-safe. +std::ostream* Logger::info_stream_ = &std::cout; +std::ostream* Logger::error_stream_ = &std::cerr; } // namespace relocation_packer diff --git a/tools/relocation_packer/src/debug.h b/tools/relocation_packer/src/debug.h index 47ee96a..d82f90a1 100644 --- a/tools/relocation_packer/src/debug.h +++ b/tools/relocation_packer/src/debug.h @@ -2,87 +2,115 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Logging and checks. +// Logging and checks. Avoids a dependency on base. // -// Log messages to stdout. LOG() prints normal user messages, VLOG() -// is verbose, for tracing and debugging. SetVerbose() enables/disables -// VLOG() output. +// LOG(tag) prints messages. Tags are INFO, WARNING, ERROR and FATAL. +// INFO prints to stdout, the others to stderr. FATAL aborts after printing. // -// LOG() and VLOG() are printf-like, and arguments are checked by gcc. -// LOG_IF() and VLOG_IF() call LOG/VLOG if their predicate is true. -// CHECK() aborts if its predicate is false. NOTREACHED() always aborts. -// Logging is not thread-safe. +// LOG_IF(tag, predicate) logs if predicate evaluates to true, else silent. +// +// VLOG(level) logs INFO messages where level is less than or equal to the +// verbosity level set with SetVerbose(). +// +// VLOG_IF(level, predicate) logs INFO if predicate evaluates to true, +// else silent. +// +// CHECK(predicate) logs a FATAL error if predicate is false. +// NOTREACHED() always aborts. +// Log streams can be changed with SetStreams(). Logging is not thread-safe. // #ifndef TOOLS_RELOCATION_PACKER_SRC_DEBUG_H_ #define TOOLS_RELOCATION_PACKER_SRC_DEBUG_H_ -#ifdef NDEBUG -#undef NDEBUG -#include <assert.h> -#define NDEBUG -#else -#include <assert.h> -#endif - -#include <stdarg.h> -#include <string.h> +#include <limits.h> +#include <algorithm> +#include <ostream> +#include <sstream> namespace relocation_packer { -// If gcc, define PRINTF_ATTRIBUTE so that gcc checks Log() as printf-like. -#if defined(__GNUC__) && (__GNUC__ >= 3) -#define PRINTF_ATTRIBUTE(string_index, first_to_check) \ - __attribute__((__format__(__printf__, string_index, first_to_check))) -#else -#define PRINTF_ATTRIBUTE(string_index, first_to_check) -#endif - -// Logging and checking macros. -#define LOG(...) ::relocation_packer::Logger::Log(__VA_ARGS__) -#define VLOG(...) ::relocation_packer::Logger::VLog(__VA_ARGS__) -#define LOG_IF(cond, ...) \ - do { \ - if ((cond)) \ - LOG(__VA_ARGS__); \ - } while (0) -#define VLOG_IF(cond, ...) \ - do { \ - if ((cond)) \ - VLOG(__VA_ARGS__); \ - } while (0) - -#define CHECK(expr) assert((expr)) -#define NOTREACHED(_) assert(false) - class Logger { public: - // Log and verbose log to stdout. - // |format| is a printf format string. - static void Log(const char* format, ...) PRINTF_ATTRIBUTE(1, 2); - static void VLog(const char* format, ...) PRINTF_ATTRIBUTE(1, 2); + enum Severity {INFO = 0, WARNING, ERROR, FATAL}; + + // Construct a new message logger. Prints if level is less than or + // equal to the level set with SetVerbose() and predicate is true. + // |severity| is an enumerated severity. + // |level| is the verbosity level. + // |predicate| controls if the logger prints or is silent. + Logger(Severity severity, int level, bool predicate); - // Set verbose mode. - // |flag| is true to enable verbose logging, false to disable it. - static void SetVerbose(bool flag); + // On destruction, flush and print the strings accumulated in stream_. + ~Logger(); + + // Return the stream for this logger. + std::ostream& GetStream() { return stream_; } + + // Set verbosity level. Messages with a level less than or equal to + // this level are printed, others are discarded. Static, not thread-safe. + static void SetVerbose(int level) { max_level_ = level; } + + // Set info and error logging streams. Static, not thread-safe. + static void SetStreams(std::ostream* info_stream, + std::ostream* error_stream) { + info_stream_ = info_stream; + error_stream_ = error_stream; + } + + // Reset to initial state. + static void Reset(); private: - Logger() : is_verbose_(false) { } - ~Logger() {} + // Message severity, verbosity level, and predicate. + Severity severity_; + int level_; + bool predicate_; - // Implementation of log to stdout. - // |format| is a printf format string. - // |args| is a varargs list of printf arguments. - void Log(const char* format, va_list args); + // String stream, accumulates message text. + std::ostringstream stream_; - // If set, VLOG is enabled, otherwise it is a no-op. - bool is_verbose_; + // Verbosity for INFO messages. Not thread-safe. + static int max_level_; - // Singleton support. Not thread-safe. - static Logger* GetInstance(); - static Logger* instance_; + // Logging streams. Not thread-safe. + static std::ostream* info_stream_; + static std::ostream* error_stream_; }; } // namespace relocation_packer +// Make logging severities visible globally. +typedef relocation_packer::Logger::Severity LogSeverity; +const LogSeverity INFO = relocation_packer::Logger::INFO; +const LogSeverity WARNING = relocation_packer::Logger::WARNING; +const LogSeverity ERROR = relocation_packer::Logger::ERROR; +const LogSeverity FATAL = relocation_packer::Logger::FATAL; + +// LOG(severity) prints a message with the given severity, and aborts if +// severity is FATAL. LOG_IF(severity, predicate) does the same but only if +// predicate is true. INT_MIN is guaranteed to be less than or equal to +// any verbosity level. +#define LOG(severity) \ + (relocation_packer::Logger(severity, INT_MIN, true).GetStream()) +#define LOG_IF(severity, predicate) \ + (relocation_packer::Logger(severity, INT_MIN, (predicate)).GetStream()) + +// VLOG(level) prints its message as INFO if level is less than or equal to +// the current verbosity level. +#define VLOG(level) \ + (relocation_packer::Logger(INFO, (level), true).GetStream()) +#define VLOG_IF(level, predicate) \ + (relocation_packer::Logger(INFO, (level), (predicate)).GetStream()) + +// CHECK(predicate) fails with a FATAL log message if predicate is false. +#define CHECK(predicate) (LOG_IF(FATAL, !(predicate)) \ + << __FILE__ << ":" << __LINE__ << ": " \ + << __FUNCTION__ << ": CHECK '" #predicate "' failed") + +// NOTREACHED() always fails with a FATAL log message. +#define NOTREACHED(_) (LOG(FATAL) \ + << __FILE__ << ":" << __LINE__ << ": " \ + << __FUNCTION__ << ": NOTREACHED() hit") + #endif // TOOLS_RELOCATION_PACKER_SRC_DEBUG_H_ diff --git a/tools/relocation_packer/src/debug_unittest.cc b/tools/relocation_packer/src/debug_unittest.cc new file mode 100644 index 0000000..75608de --- /dev/null +++ b/tools/relocation_packer/src/debug_unittest.cc @@ -0,0 +1,123 @@ +// Copyright 2014 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 "debug.h" + +#include <sstream> +#include <string> +#include "testing/gtest/include/gtest/gtest.h" + +namespace relocation_packer { + +TEST(Debug, Log) { + Logger::Reset(); + std::ostringstream info; + std::ostringstream error; + Logger::SetStreams(&info, &error); + + LOG(INFO) << "INFO log message"; + LOG(WARNING) << "WARNING log message"; + LOG(ERROR) << "ERROR log message"; + + EXPECT_EQ("INFO: INFO log message\n", info.str()); + EXPECT_EQ("WARNING: WARNING log message\n" + "ERROR: ERROR log message\n", error.str()); + Logger::Reset(); +} + +TEST(Debug, LogIf) { + Logger::Reset(); + std::ostringstream info; + std::ostringstream error; + Logger::SetStreams(&info, &error); + + LOG_IF(INFO, true) << "INFO log message"; + LOG_IF(INFO, false) << "INFO log message, SHOULD NOT PRINT"; + LOG_IF(WARNING, true) << "WARNING log message"; + LOG_IF(WARNING, false) << "WARNING log message, SHOULD NOT PRINT"; + LOG_IF(ERROR, true) << "ERROR log message"; + LOG_IF(ERROR, false) << "ERROR log message, SHOULD NOT PRINT"; + LOG_IF(FATAL, false) << "FATAL log message, SHOULD NOT PRINT"; + + EXPECT_EQ("INFO: INFO log message\n", info.str()); + EXPECT_EQ("WARNING: WARNING log message\n" + "ERROR: ERROR log message\n", error.str()); + Logger::Reset(); +} + +TEST(Debug, Vlog) { + Logger::Reset(); + std::ostringstream info; + std::ostringstream error; + Logger::SetStreams(&info, &error); + + VLOG(0) << "VLOG 0 INFO log message, SHOULD NOT PRINT"; + VLOG(1) << "VLOG 1 INFO log message, SHOULD NOT PRINT"; + VLOG(2) << "VLOG 2 INFO log message, SHOULD NOT PRINT"; + + EXPECT_EQ("", info.str()); + EXPECT_EQ("", error.str()); + + Logger::SetVerbose(1); + + VLOG(0) << "VLOG 0 INFO log message"; + VLOG(1) << "VLOG 1 INFO log message"; + VLOG(2) << "VLOG 2 INFO log message, SHOULD NOT PRINT"; + + EXPECT_EQ("INFO: VLOG 0 INFO log message\n" + "INFO: VLOG 1 INFO log message\n", info.str()); + EXPECT_EQ("", error.str()); + Logger::Reset(); +} + +TEST(Debug, VlogIf) { + Logger::Reset(); + std::ostringstream info; + std::ostringstream error; + Logger::SetStreams(&info, &error); + + VLOG_IF(0, true) << "VLOG 0 INFO log message, SHOULD NOT PRINT"; + VLOG_IF(1, true) << "VLOG 1 INFO log message, SHOULD NOT PRINT"; + VLOG_IF(2, true) << "VLOG 2 INFO log message, SHOULD NOT PRINT"; + + EXPECT_EQ("", info.str()); + EXPECT_EQ("", error.str()); + + Logger::SetVerbose(1); + + VLOG_IF(0, true) << "VLOG 0 INFO log message"; + VLOG_IF(0, false) << "VLOG 0 INFO log message, SHOULD NOT PRINT"; + VLOG_IF(1, true) << "VLOG 1 INFO log message"; + VLOG_IF(1, false) << "VLOG 1 INFO log message, SHOULD NOT PRINT"; + VLOG_IF(2, true) << "VLOG 2 INFO log message, SHOULD NOT PRINT"; + VLOG_IF(2, false) << "VLOG 2 INFO log message, SHOULD NOT PRINT"; + + EXPECT_EQ("INFO: VLOG 0 INFO log message\n" + "INFO: VLOG 1 INFO log message\n", info.str()); + EXPECT_EQ("", error.str()); + Logger::Reset(); +} + +TEST(DebugDeathTest, Fatal) { + ::testing::FLAGS_gtest_death_test_style = "threadsafe"; + Logger::Reset(); + EXPECT_DEATH(LOG(FATAL) << "FATAL log message", "FATAL: FATAL log message"); + EXPECT_DEATH( + LOG_IF(FATAL, true) << "FATAL log message", "FATAL: FATAL log message"); +} + +TEST(DebugDeathTest, Check) { + ::testing::FLAGS_gtest_death_test_style = "threadsafe"; + Logger::Reset(); + CHECK(0 == 0); + EXPECT_DEATH(CHECK(0 == 1), "FATAL: .*:.*: .*: CHECK '0 == 1' failed"); +} + +TEST(DebugDeathTest, NotReached) { + ::testing::FLAGS_gtest_death_test_style = "threadsafe"; + Logger::Reset(); + EXPECT_DEATH(NOTREACHED(), "FATAL: .*:.*: .*: NOTREACHED\\(\\) hit"); +} + +} // namespace relocation_packer diff --git a/tools/relocation_packer/src/elf_file.cc b/tools/relocation_packer/src/elf_file.cc index c1008f2..6399018 100644 --- a/tools/relocation_packer/src/elf_file.cc +++ b/tools/relocation_packer/src/elf_file.cc @@ -56,13 +56,13 @@ void RewriteSectionData(Elf_Data* data, // Verbose ELF header logging. void VerboseLogElfHeader(const Elf32_Ehdr* elf_header) { - VLOG("e_phoff = %u\n", elf_header->e_phoff); - VLOG("e_shoff = %u\n", elf_header->e_shoff); - VLOG("e_ehsize = %u\n", elf_header->e_ehsize); - VLOG("e_phentsize = %u\n", elf_header->e_phentsize); - VLOG("e_phnum = %u\n", elf_header->e_phnum); - VLOG("e_shnum = %u\n", elf_header->e_shnum); - VLOG("e_shstrndx = %u\n", elf_header->e_shstrndx); + VLOG(1) << "e_phoff = " << elf_header->e_phoff; + VLOG(1) << "e_shoff = " << elf_header->e_shoff; + VLOG(1) << "e_ehsize = " << elf_header->e_ehsize; + VLOG(1) << "e_phentsize = " << elf_header->e_phentsize; + VLOG(1) << "e_phnum = " << elf_header->e_phnum; + VLOG(1) << "e_shnum = " << elf_header->e_shnum; + VLOG(1) << "e_shstrndx = " << elf_header->e_shstrndx; } // Verbose ELF program header logging. @@ -80,31 +80,31 @@ void VerboseLogProgramHeader(size_t program_header_index, case PT_TLS: type = "TLS"; break; default: type = "(OTHER)"; break; } - VLOG("phdr %lu : %s\n", program_header_index, type.c_str()); - VLOG(" p_offset = %u\n", program_header->p_offset); - VLOG(" p_vaddr = %u\n", program_header->p_vaddr); - VLOG(" p_paddr = %u\n", program_header->p_paddr); - VLOG(" p_filesz = %u\n", program_header->p_filesz); - VLOG(" p_memsz = %u\n", program_header->p_memsz); + VLOG(1) << "phdr " << program_header_index << " : " << type; + VLOG(1) << " p_offset = " << program_header->p_offset; + VLOG(1) << " p_vaddr = " << program_header->p_vaddr; + VLOG(1) << " p_paddr = " << program_header->p_paddr; + VLOG(1) << " p_filesz = " << program_header->p_filesz; + VLOG(1) << " p_memsz = " << program_header->p_memsz; } // Verbose ELF section header logging. void VerboseLogSectionHeader(const std::string& section_name, const Elf32_Shdr* section_header) { - VLOG("section %s\n", section_name.c_str()); - VLOG(" sh_addr = %u\n", section_header->sh_addr); - VLOG(" sh_offset = %u\n", section_header->sh_offset); - VLOG(" sh_size = %u\n", section_header->sh_size); - VLOG(" sh_addralign = %u\n", section_header->sh_addralign); + VLOG(1) << "section " << section_name; + VLOG(1) << " sh_addr = " << section_header->sh_addr; + VLOG(1) << " sh_offset = " << section_header->sh_offset; + VLOG(1) << " sh_size = " << section_header->sh_size; + VLOG(1) << " sh_addralign = " << section_header->sh_addralign; } // Verbose ELF section data logging. void VerboseLogSectionData(const Elf_Data* data) { - VLOG(" data\n"); - VLOG(" d_buf = %p\n", data->d_buf); - VLOG(" d_off = %lu\n", data->d_off); - VLOG(" d_size = %lu\n", data->d_size); - VLOG(" d_align = %lu\n", data->d_align); + VLOG(1) << " data"; + VLOG(1) << " d_buf = " << data->d_buf; + VLOG(1) << " d_off = " << data->d_off; + VLOG(1) << " d_size = " << data->d_size; + VLOG(1) << " d_align = " << data->d_align; } } // namespace @@ -120,17 +120,17 @@ bool ElfFile::Load() { CHECK(elf_); if (elf_kind(elf_) != ELF_K_ELF) { - LOG("ERROR: File not in ELF format\n"); + LOG(ERROR) << "File not in ELF format"; return false; } Elf32_Ehdr* elf_header = elf32_getehdr(elf_); if (!elf_header) { - LOG("ERROR: Failed to load ELF header\n"); + LOG(ERROR) << "Failed to load ELF header"; return false; } if (elf_header->e_machine != EM_ARM) { - LOG("ERROR: File is not an arm32 ELF file\n"); + LOG(ERROR) << "File is not an arm32 ELF file"; return false; } @@ -140,7 +140,7 @@ bool ElfFile::Load() { CHECK(endian == ELFDATA2LSB); CHECK(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__); - VLOG("endian = %u\n", endian); + VLOG(1) << "endian = " << endian; VerboseLogElfHeader(elf_header); const Elf32_Phdr* elf_program_header = elf32_getphdr(elf_); @@ -208,21 +208,22 @@ bool ElfFile::Load() { // Loading failed if we did not find the required special sections. if (!found_rel_dyn_section) { - LOG("ERROR: Missing .rel.dyn section\n"); + LOG(ERROR) << "Missing .rel.dyn section"; return false; } if (!found_dynamic_section) { - LOG("ERROR: Missing .dynamic section\n"); + LOG(ERROR) << "Missing .dynamic section"; return false; } if (!found_android_rel_dyn_section) { - LOG("ERROR: Missing .android.rel.dyn section " - "(to fix, run with --help and follow the pre-packing instructions)\n"); + LOG(ERROR) << "Missing .android.rel.dyn section " + << "(to fix, run with --help and follow the pre-packing " + << "instructions)"; return false; } if (has_debug_section) { - LOG("WARNING: found .debug section(s), and ignored them\n"); + LOG(WARNING) << "Found .debug section(s), and ignored them"; } rel_dyn_section_ = found_rel_dyn_section; @@ -239,11 +240,11 @@ void AdjustElfHeaderForHole(Elf32_Ehdr* elf_header, int32_t hole_size) { if (elf_header->e_phoff > hole_start) { elf_header->e_phoff += hole_size; - VLOG("e_phoff adjusted to %u\n", elf_header->e_phoff); + VLOG(1) << "e_phoff adjusted to " << elf_header->e_phoff; } if (elf_header->e_shoff > hole_start) { elf_header->e_shoff += hole_size; - VLOG("e_shoff adjusted to %u\n", elf_header->e_shoff); + VLOG(1) << "e_shoff adjusted to " << elf_header->e_shoff; } } @@ -258,25 +259,30 @@ void AdjustProgramHeadersForHole(Elf32_Phdr* elf_program_header, if (program_header->p_offset > hole_start) { // The hole start is past this segment, so adjust offsets and addrs. program_header->p_offset += hole_size; - VLOG("phdr %lu p_offset adjusted to %u\n", i, program_header->p_offset); + VLOG(1) << "phdr " << i + << " p_offset adjusted to "<< program_header->p_offset; // Only adjust vaddr and paddr if this program header has them. if (program_header->p_vaddr != 0) { program_header->p_vaddr += hole_size; - VLOG("phdr %lu p_vaddr adjusted to %u\n", i, program_header->p_vaddr); + VLOG(1) << "phdr " << i + << " p_vaddr adjusted to " << program_header->p_vaddr; } if (program_header->p_paddr != 0) { program_header->p_paddr += hole_size; - VLOG("phdr %lu p_paddr adjusted to %u\n", i, program_header->p_paddr); + VLOG(1) << "phdr " << i + << " p_paddr adjusted to " << program_header->p_paddr; } } else if (program_header->p_offset + program_header->p_filesz > hole_start) { // The hole start is within this segment, so adjust file and in-memory // sizes, but leave offsets and addrs unchanged. program_header->p_filesz += hole_size; - VLOG("phdr %lu p_filesz adjusted to %u\n", i, program_header->p_filesz); + VLOG(1) << "phdr " << i + << " p_filesz adjusted to " << program_header->p_filesz; program_header->p_memsz += hole_size; - VLOG("phdr %lu p_memsz adjusted to %u\n", i, program_header->p_memsz); + VLOG(1) << "phdr " << i + << " p_memsz adjusted to " << program_header->p_memsz; } } } @@ -295,13 +301,13 @@ void AdjustSectionHeadersForHole(Elf* elf, if (section_header->sh_offset > hole_start) { section_header->sh_offset += hole_size; - VLOG("section %s sh_offset" - " adjusted to %u\n", name.c_str(), section_header->sh_offset); + VLOG(1) << "section " << name + << " sh_offset adjusted to " << section_header->sh_offset; // Only adjust section addr if this section has one. if (section_header->sh_addr != 0) { section_header->sh_addr += hole_size; - VLOG("section %s sh_addr" - " adjusted to %u\n", name.c_str(), section_header->sh_addr); + VLOG(1) << "section " << name + << " sh_addr adjusted to " << section_header->sh_addr; } } } @@ -337,8 +343,8 @@ void AdjustDynamicSectionForHole(Elf_Scn* dynamic_section, tag == DT_ANDROID_ARM_REL_OFFSET); if (is_adjustable && dynamic->d_un.d_ptr > hole_start) { dynamic->d_un.d_ptr += hole_size; - VLOG("dynamic[%lu] %u" - " d_ptr adjusted to %u\n", i, dynamic->d_tag, dynamic->d_un.d_ptr); + VLOG(1) << "dynamic[" << i << "] " << dynamic->d_tag + << " d_ptr adjusted to " << dynamic->d_un.d_ptr; } // If we are specifically resizing .rel.dyn, we need to make some added @@ -348,20 +354,20 @@ void AdjustDynamicSectionForHole(Elf_Scn* dynamic_section, // DT_RELSZ is the overall size of relocations. Adjust by hole size. if (tag == DT_RELSZ) { dynamic->d_un.d_val += hole_size; - VLOG("dynamic[%lu] %u" - " d_val adjusted to %u\n", i, dynamic->d_tag, dynamic->d_un.d_val); + VLOG(1) << "dynamic[" << i << "] " << dynamic->d_tag + << " d_val adjusted to " << dynamic->d_un.d_val; } - // The crazy linker does not use DT_RELCOUNT, but we keep it updated - // anyway. In practice the section hole is always equal to the size - // of R_ARM_RELATIVE relocations, and DT_RELCOUNT is the count of - // relative relocations. So closing a hole on packing reduces - // DT_RELCOUNT to zero, and opening a hole on unpacking restores it to - // its pre-packed value. + // DT_RELCOUNT is the count of relative relocations. Packing reduces it + // to the alignment padding, if any; unpacking restores it to its former + // value. The crazy linker does not use it, but we update it anyway. if (tag == DT_RELCOUNT) { - dynamic->d_un.d_val += hole_size / sizeof(Elf32_Rel); - VLOG("dynamic[%lu] %u" - " d_val adjusted to %u\n", i, dynamic->d_tag, dynamic->d_un.d_val); + // Cast sizeof to a signed type to avoid the division result being + // promoted into an unsigned size_t. + const ssize_t sizeof_rel = static_cast<ssize_t>(sizeof(Elf32_Rel)); + dynamic->d_un.d_val += hole_size / sizeof_rel; + VLOG(1) << "dynamic[" << i << "] " << dynamic->d_tag + << " d_val adjusted to " << dynamic->d_un.d_val; } // DT_RELENT doesn't change, but make sure it is what we expect. @@ -399,8 +405,8 @@ void AdjustDynSymSectionForHole(Elf_Scn* dynsym_section, type == STT_TLS); if (is_adjustable && dynsym->st_value > hole_start) { dynsym->st_value += hole_size; - VLOG("dynsym[%lu] type=%u" - " st_value adjusted to %u\n", i, type, dynsym->st_value); + VLOG(1) << "dynsym[" << i << "] type=" << type + << " st_value adjusted to " << dynsym->st_value; } } @@ -426,7 +432,8 @@ void AdjustRelPltSectionForHole(Elf_Scn* relplt_section, Elf32_Rel* relplt = &relplts[i]; if (relplt->r_offset > hole_start) { relplt->r_offset += hole_size; - VLOG("relplt[%lu] r_offset adjusted to %u\n", i, relplt->r_offset); + VLOG(1) << "relplt[" << i + << "] r_offset adjusted to " << relplt->r_offset; } } @@ -452,7 +459,7 @@ void AdjustSymTabSectionForHole(Elf_Scn* symtab_section, Elf32_Sym* sym = &symtab[i]; if (sym->st_value > hole_start) { sym->st_value += hole_size; - VLOG("symtab[%lu] value adjusted to %u\n", i, sym->st_value); + VLOG(1) << "symtab[" << i << "] value adjusted to " << sym->st_value; } } @@ -490,8 +497,8 @@ void ResizeSection(Elf* elf, Elf_Scn* section, size_t new_size) { const Elf32_Off hole_start = section_header->sh_offset; const int32_t hole_size = new_size - data->d_size; - VLOG_IF(hole_size > 0, "expand section size = %lu\n", data->d_size); - VLOG_IF(hole_size < 0, "shrink section size = %lu\n", data->d_size); + VLOG_IF(1, (hole_size > 0)) << "expand section size = " << data->d_size; + VLOG_IF(1, (hole_size < 0)) << "shrink section size = " << data->d_size; // Resize the data and the section header. data->d_size += hole_size; @@ -595,15 +602,14 @@ void AddDynamicEntry(Elf32_Dyn dyn, Elf32_Dyn &slot = dynamics->at(i); if (slot.d_tag == DT_NULL) { slot = dyn; - VLOG("dynamic[%lu] overwritten with %u\n", i, dyn.d_tag); + VLOG(1) << "dynamic[" << i << "] overwritten with " << dyn.d_tag; return; } } // No free dynamics vector slot was found. - LOG("FATAL: No spare dynamic vector slots found " - "(to fix, increase gold's --spare-dynamic-tags value)\n"); - NOTREACHED(); + LOG(FATAL) << "No spare dynamic vector slots found " + << "(to fix, increase gold's --spare-dynamic-tags value)"; } // Remove the element in the dynamics vector that matches the given tag with @@ -617,7 +623,8 @@ void RemoveDynamicEntry(Elf32_Sword tag, if (slot.d_tag == tag) { for ( ; i < dynamics->size() - 1; ++i) { dynamics->at(i) = dynamics->at(i + 1); - VLOG("dynamic[%lu] overwritten with dynamic[%lu]\n", i, i + 1); + VLOG(1) << "dynamic[" << i + << "] overwritten with dynamic[" << i + 1 << "]"; } CHECK(dynamics->at(i).d_tag == DT_NULL); return; @@ -673,7 +680,7 @@ void AdjustRelocationTargets(Elf* elf, } *target += hole_size; - VLOG("relocation[%lu] target adjusted to %u\n", i, *target); + VLOG(1) << "relocation[" << i << "] target adjusted to " << *target; } } } @@ -704,7 +711,8 @@ void AdjustRelocations(Elf32_Off hole_start, Elf32_Rel* relocation = &relocations->at(i); if (relocation->r_offset > hole_start) { relocation->r_offset += hole_size; - VLOG("relocation[%lu] offset adjusted to %u\n", i, relocation->r_offset); + VLOG(1) << "relocation[" << i + << "] offset adjusted to " << relocation->r_offset; } } } @@ -716,7 +724,7 @@ void AdjustRelocations(Elf32_Off hole_start, bool ElfFile::PackRelocations() { // Load the ELF file into libelf. if (!Load()) { - LOG("ERROR: Failed to load as ELF (elf_error=%d)\n", elf_errno()); + LOG(ERROR) << "Failed to load as ELF (elf_error=" << elf_errno() << ")"; return false; } @@ -742,14 +750,14 @@ bool ElfFile::PackRelocations() { other_relocations.push_back(relocation); } } - LOG("R_ARM_RELATIVE: %lu entries\n", relative_relocations.size()); - LOG("Other : %lu entries\n", other_relocations.size()); - LOG("Total : %lu entries\n", relocations.size()); + LOG(INFO) << "R_ARM_RELATIVE: " << relative_relocations.size() << " entries"; + LOG(INFO) << "Other : " << other_relocations.size() << " entries"; + LOG(INFO) << "Total : " << relocations.size() << " entries"; // If no relative relocations then we have nothing packable. Perhaps // the shared object has already been packed? if (relative_relocations.empty()) { - LOG("ERROR: No R_ARM_RELATIVE relocations found (already packed?)\n"); + LOG(ERROR) << "No R_ARM_RELATIVE relocations found (already packed?)"; return false; } @@ -766,11 +774,11 @@ bool ElfFile::PackRelocations() { // Adjust the actual hole size to preserve alignment. hole_size -= hole_size % kPreserveAlignment; - LOG("Compaction : %lu bytes\n", hole_size); + LOG(INFO) << "Compaction : " << hole_size << " bytes"; // Adjusting for alignment may have removed any packing benefit. if (hole_size == 0) { - LOG("Too few R_ARM_RELATIVE relocations to pack after alignment\n"); + LOG(INFO) << "Too few R_ARM_RELATIVE relocations to pack after alignment"; return false; } @@ -779,7 +787,7 @@ bool ElfFile::PackRelocations() { CHECK(padding_bytes % sizeof(other_relocations[0]) == 0); const size_t required = padding_bytes / sizeof(other_relocations[0]); PadRelocations(required, &other_relocations); - LOG("Alignment pad : %lu relocations\n", required); + LOG(INFO) << "Alignment pad : " << required << " relocations"; // Apply relocations to all R_ARM_RELATIVE data to relocate it into the // area it will occupy once the hole in .rel.dyn is removed. @@ -799,18 +807,18 @@ bool ElfFile::PackRelocations() { // Pack R_ARM_RELATIVE relocations. const size_t initial_bytes = relative_relocations.size() * sizeof(relative_relocations[0]); - LOG("Unpacked R_ARM_RELATIVE: %lu bytes\n", initial_bytes); + LOG(INFO) << "Unpacked R_ARM_RELATIVE: " << initial_bytes << " bytes"; std::vector<uint8_t> packed; RelocationPacker packer; packer.PackRelativeRelocations(relative_relocations, &packed); const void* packed_data = &packed[0]; const size_t packed_bytes = packed.size() * sizeof(packed[0]); - LOG("Packed R_ARM_RELATIVE: %lu bytes\n", packed_bytes); + LOG(INFO) << "Packed R_ARM_RELATIVE: " << packed_bytes << " bytes"; // If we have insufficient R_ARM_RELATIVE relocations to form a run then // packing fails. if (packed.empty()) { - LOG("Too few R_ARM_RELATIVE relocations to pack\n"); + LOG(INFO) << "Too few R_ARM_RELATIVE relocations to pack"; return false; } @@ -825,7 +833,7 @@ bool ElfFile::PackRelocations() { // Make sure packing saved some space. if (packed_bytes >= initial_bytes) { - LOG("Packing R_ARM_RELATIVE relocations saves no space\n"); + LOG(INFO) << "Packing R_ARM_RELATIVE relocations saves no space"; return false; } @@ -869,7 +877,7 @@ bool ElfFile::PackRelocations() { bool ElfFile::UnpackRelocations() { // Load the ELF file into libelf. if (!Load()) { - LOG("ERROR: Failed to load as ELF (elf_error=%d)\n", elf_errno()); + LOG(ERROR) << "Failed to load as ELF (elf_error=" << elf_errno() << ")"; return false; } @@ -886,19 +894,19 @@ bool ElfFile::UnpackRelocations() { if (packed.empty() || packed[0] != 'A' || packed[1] != 'P' || packed[2] != 'R' || packed[3] != '1') { - LOG("ERROR: Packed R_ARM_RELATIVE relocations not found (not packed?)\n"); + LOG(ERROR) << "Packed R_ARM_RELATIVE relocations not found (not packed?)"; return false; } // Unpack the data to re-materialize the R_ARM_RELATIVE relocations. const size_t packed_bytes = packed.size() * sizeof(packed[0]); - LOG("Packed R_ARM_RELATIVE: %lu bytes\n", packed_bytes); + LOG(INFO) << "Packed R_ARM_RELATIVE: " << packed_bytes << " bytes"; std::vector<Elf32_Rel> relative_relocations; RelocationPacker packer; packer.UnpackRelativeRelocations(packed, &relative_relocations); const size_t unpacked_bytes = relative_relocations.size() * sizeof(relative_relocations[0]); - LOG("Unpacked R_ARM_RELATIVE: %lu bytes\n", unpacked_bytes); + LOG(INFO) << "Unpacked R_ARM_RELATIVE: " << unpacked_bytes << " bytes"; // Retrieve the current .rel.dyn section data. data = GetSectionData(rel_dyn_section_); @@ -922,8 +930,8 @@ bool ElfFile::UnpackRelocations() { ++padding; } } - LOG("R_ARM_RELATIVE: %lu entries\n", relative_relocations.size()); - LOG("Other : %lu entries\n", other_relocations.size()); + LOG(INFO) << "R_ARM_RELATIVE: " << relative_relocations.size() << " entries"; + LOG(INFO) << "Other : " << other_relocations.size() << " entries"; // If we found the same number of R_ARM_NONE entries in .rel.dyn as we // hold as unpacked relative relocations, then this is a padded file. @@ -941,7 +949,7 @@ bool ElfFile::UnpackRelocations() { // Adjust the hole size for the padding added to preserve alignment. hole_size -= padding * sizeof(other_relocations[0]); - LOG("Expansion : %lu bytes\n", hole_size); + LOG(INFO) << "Expansion : " << hole_size << " bytes"; // Apply relocations to all R_ARM_RELATIVE data to relocate it into the // area it will occupy once the hole in .rel.dyn is opened. @@ -960,7 +968,7 @@ bool ElfFile::UnpackRelocations() { other_relocations.begin(), other_relocations.end()); const void* section_data = &relocations[0]; const size_t bytes = relocations.size() * sizeof(relocations[0]); - LOG("Total : %lu entries\n", relocations.size()); + LOG(INFO) << "Total : " << relocations.size() << " entries"; ResizeSection(elf_, rel_dyn_section_, bytes); RewriteSectionData(data, section_data, bytes); @@ -999,7 +1007,7 @@ void ElfFile::Flush() { // Write ELF data back to disk. const off_t file_bytes = elf_update(elf_, ELF_C_WRITE); CHECK(file_bytes > 0); - VLOG("elf_update returned: %lu\n", file_bytes); + VLOG(1) << "elf_update returned: " << file_bytes; // Clean up libelf, and truncate the output file to the number of bytes // written by elf_update(). diff --git a/tools/relocation_packer/src/main.cc b/tools/relocation_packer/src/main.cc index 4bc09b6..d5ff83c 100644 --- a/tools/relocation_packer/src/main.cc +++ b/tools/relocation_packer/src/main.cc @@ -29,7 +29,8 @@ #include "debug.h" #include "elf_file.h" #include "libelf.h" -#include "packer.h" + +namespace { void PrintUsage(const char* argv0) { std::string temporary = argv0; @@ -66,6 +67,8 @@ void PrintUsage(const char* argv0) { basename, basename, basename); } +} // namespace + int main(int argc, char* argv[]) { bool is_unpacking = false; bool is_verbose = false; @@ -92,7 +95,7 @@ int main(int argc, char* argv[]) { PrintUsage(argv[0]); return 0; case '?': - LOG("Try '%s --help' for more information.\n", argv[0]); + LOG(INFO) << "Try '" << argv[0] << " --help' for more information."; return 1; case -1: has_options = false; @@ -102,22 +105,23 @@ int main(int argc, char* argv[]) { } } if (optind != argc - 1) { - LOG("Try '%s --help' for more information.\n", argv[0]); + LOG(INFO) << "Try '" << argv[0] << " --help' for more information."; return 1; } if (elf_version(EV_CURRENT) == EV_NONE) { - LOG("WARNING: Elf Library is out of date!\n"); + LOG(WARNING) << "Elf Library is out of date!"; } const char* file = argv[argc - 1]; const int fd = open(file, O_RDWR); if (fd == -1) { - LOG("%s: %s\n", file, strerror(errno)); + LOG(ERROR) << file << ": " << strerror(errno); return 1; } - relocation_packer::Logger::SetVerbose(is_verbose); + if (is_verbose) + relocation_packer::Logger::SetVerbose(1); relocation_packer::ElfFile elf_file(fd); elf_file.SetPadding(is_padding); @@ -131,7 +135,7 @@ int main(int argc, char* argv[]) { close(fd); if (!status) { - LOG("ERROR: %s: failed to pack/unpack file\n", file); + LOG(ERROR) << file << ": failed to pack/unpack file"; return 1; } |