123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- // Copyright (c) 2012 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/location.h"
- #include "base/compiler_specific.h"
- #include "base/strings/string_number_conversions.h"
- #include "base/strings/stringprintf.h"
- #include "base/trace_event/base_tracing.h"
- #include "build/build_config.h"
- #if defined(COMPILER_MSVC)
- #include <intrin.h>
- #endif
- namespace base {
- namespace {
- // Returns the length of the given null terminated c-string.
- constexpr size_t StrLen(const char* str) {
- size_t str_len = 0;
- for (str_len = 0; str[str_len] != '\0'; ++str_len)
- ;
- return str_len;
- }
- // Finds the length of the build folder prefix from the file path.
- // TODO(ssid): Strip prefixes from stored strings in the binary. This code only
- // skips the prefix while reading the file name strings at runtime.
- constexpr size_t StrippedFilePathPrefixLength() {
- constexpr char path[] = __FILE__;
- // Only keep the file path starting from the src directory.
- #if defined(__clang__) && defined(_MSC_VER)
- constexpr char stripped[] = "base\\location.cc";
- #else
- constexpr char stripped[] = "base/location.cc";
- #endif
- constexpr size_t path_len = StrLen(path);
- constexpr size_t stripped_len = StrLen(stripped);
- static_assert(path_len >= stripped_len,
- "Invalid file path for base/location.cc.");
- return path_len - stripped_len;
- }
- constexpr size_t kStrippedPrefixLength = StrippedFilePathPrefixLength();
- // Returns true if the |name| string has |prefix_len| characters in the prefix
- // and the suffix matches the |expected| string.
- // TODO(ssid): With C++20 we can make base::EndsWith() constexpr and use it
- // instead.
- constexpr bool StrEndsWith(const char* name,
- size_t prefix_len,
- const char* expected) {
- const size_t name_len = StrLen(name);
- const size_t expected_len = StrLen(expected);
- if (name_len != prefix_len + expected_len)
- return false;
- for (size_t i = 0; i < expected_len; ++i) {
- if (name[i + prefix_len] != expected[i])
- return false;
- }
- return true;
- }
- #if defined(__clang__) && defined(_MSC_VER)
- static_assert(StrEndsWith(__FILE__, kStrippedPrefixLength, "base\\location.cc"),
- "The file name does not match the expected prefix format.");
- #else
- static_assert(StrEndsWith(__FILE__, kStrippedPrefixLength, "base/location.cc"),
- "The file name does not match the expected prefix format.");
- #endif
- } // namespace
- Location::Location() = default;
- Location::Location(const Location& other) = default;
- Location::Location(Location&& other) noexcept = default;
- Location& Location::operator=(const Location& other) = default;
- Location::Location(const char* file_name, const void* program_counter)
- : file_name_(file_name), program_counter_(program_counter) {}
- Location::Location(const char* function_name,
- const char* file_name,
- int line_number,
- const void* program_counter)
- : function_name_(function_name),
- file_name_(file_name),
- line_number_(line_number),
- program_counter_(program_counter) {
- #if !BUILDFLAG(IS_NACL)
- // The program counter should not be null except in a default constructed
- // (empty) Location object. This value is used for identity, so if it doesn't
- // uniquely identify a location, things will break.
- //
- // The program counter isn't supported in NaCl so location objects won't work
- // properly in that context.
- DCHECK(program_counter);
- #endif
- }
- std::string Location::ToString() const {
- if (has_source_info()) {
- return std::string(function_name_) + "@" + file_name_ + ":" +
- NumberToString(line_number_);
- }
- return StringPrintf("pc:%p", program_counter_);
- }
- void Location::WriteIntoTrace(perfetto::TracedValue context) const {
- auto dict = std::move(context).WriteDictionary();
- dict.Add("function_name", function_name_);
- dict.Add("file_name", file_name_);
- dict.Add("line_number", line_number_);
- }
- #if defined(COMPILER_MSVC)
- #define RETURN_ADDRESS() _ReturnAddress()
- #elif defined(COMPILER_GCC) && !BUILDFLAG(IS_NACL)
- #define RETURN_ADDRESS() \
- __builtin_extract_return_addr(__builtin_return_address(0))
- #else
- #define RETURN_ADDRESS() nullptr
- #endif
- #if !BUILDFLAG(FROM_HERE_USES_LOCATION_BUILTINS)
- #if !BUILDFLAG(ENABLE_LOCATION_SOURCE)
- // static
- NOINLINE Location Location::CreateFromHere(const char* file_name) {
- return Location(file_name + kStrippedPrefixLength, RETURN_ADDRESS());
- }
- #else
- // static
- NOINLINE Location Location::CreateFromHere(const char* function_name,
- const char* file_name,
- int line_number) {
- return Location(function_name, file_name + kStrippedPrefixLength, line_number,
- RETURN_ADDRESS());
- }
- #endif
- #endif
- #if SUPPORTS_LOCATION_BUILTINS && BUILDFLAG(ENABLE_LOCATION_SOURCE)
- // static
- NOINLINE Location Location::Current(const char* function_name,
- const char* file_name,
- int line_number) {
- return Location(function_name, file_name + kStrippedPrefixLength, line_number,
- RETURN_ADDRESS());
- }
- #elif SUPPORTS_LOCATION_BUILTINS
- // static
- NOINLINE Location Location::Current(const char* file_name) {
- return Location(file_name + kStrippedPrefixLength, RETURN_ADDRESS());
- }
- #else
- // static
- NOINLINE Location Location::Current() {
- return Location(nullptr, RETURN_ADDRESS());
- }
- #endif
- //------------------------------------------------------------------------------
- NOINLINE const void* GetProgramCounter() {
- return RETURN_ADDRESS();
- }
- } // namespace base
|