xref: /aosp_15_r20/external/cronet/base/location.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "base/location.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include "base/compiler_specific.h"
8*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_number_conversions.h"
9*6777b538SAndroid Build Coastguard Worker #include "base/strings/stringprintf.h"
10*6777b538SAndroid Build Coastguard Worker #include "base/trace_event/base_tracing.h"
11*6777b538SAndroid Build Coastguard Worker 
12*6777b538SAndroid Build Coastguard Worker #if defined(COMPILER_MSVC)
13*6777b538SAndroid Build Coastguard Worker #include <intrin.h>
14*6777b538SAndroid Build Coastguard Worker #endif
15*6777b538SAndroid Build Coastguard Worker 
16*6777b538SAndroid Build Coastguard Worker namespace base {
17*6777b538SAndroid Build Coastguard Worker 
18*6777b538SAndroid Build Coastguard Worker namespace {
19*6777b538SAndroid Build Coastguard Worker 
20*6777b538SAndroid Build Coastguard Worker // Returns the length of the given null terminated c-string.
StrLen(const char * str)21*6777b538SAndroid Build Coastguard Worker constexpr size_t StrLen(const char* str) {
22*6777b538SAndroid Build Coastguard Worker   size_t str_len = 0;
23*6777b538SAndroid Build Coastguard Worker   for (str_len = 0; str[str_len] != '\0'; ++str_len)
24*6777b538SAndroid Build Coastguard Worker     ;
25*6777b538SAndroid Build Coastguard Worker   return str_len;
26*6777b538SAndroid Build Coastguard Worker }
27*6777b538SAndroid Build Coastguard Worker 
28*6777b538SAndroid Build Coastguard Worker // Finds the length of the build folder prefix from the file path.
29*6777b538SAndroid Build Coastguard Worker // TODO(ssid): Strip prefixes from stored strings in the binary. This code only
30*6777b538SAndroid Build Coastguard Worker // skips the prefix while reading the file name strings at runtime.
StrippedFilePathPrefixLength()31*6777b538SAndroid Build Coastguard Worker constexpr size_t StrippedFilePathPrefixLength() {
32*6777b538SAndroid Build Coastguard Worker   constexpr char path[] = __FILE__;
33*6777b538SAndroid Build Coastguard Worker   // Only keep the file path starting from the src directory.
34*6777b538SAndroid Build Coastguard Worker #if defined(__clang__) && defined(_MSC_VER)
35*6777b538SAndroid Build Coastguard Worker   constexpr char stripped[] = "base\\location.cc";
36*6777b538SAndroid Build Coastguard Worker #else
37*6777b538SAndroid Build Coastguard Worker   constexpr char stripped[] = "base/location.cc";
38*6777b538SAndroid Build Coastguard Worker #endif
39*6777b538SAndroid Build Coastguard Worker   constexpr size_t path_len = StrLen(path);
40*6777b538SAndroid Build Coastguard Worker   constexpr size_t stripped_len = StrLen(stripped);
41*6777b538SAndroid Build Coastguard Worker   static_assert(path_len >= stripped_len,
42*6777b538SAndroid Build Coastguard Worker                 "Invalid file path for base/location.cc.");
43*6777b538SAndroid Build Coastguard Worker   return path_len - stripped_len;
44*6777b538SAndroid Build Coastguard Worker }
45*6777b538SAndroid Build Coastguard Worker 
46*6777b538SAndroid Build Coastguard Worker constexpr size_t kStrippedPrefixLength = StrippedFilePathPrefixLength();
47*6777b538SAndroid Build Coastguard Worker 
48*6777b538SAndroid Build Coastguard Worker // Returns true if the |name| string has |prefix_len| characters in the prefix
49*6777b538SAndroid Build Coastguard Worker // and the suffix matches the |expected| string.
50*6777b538SAndroid Build Coastguard Worker // TODO(ssid): With C++20 we can make base::EndsWith() constexpr and use it
51*6777b538SAndroid Build Coastguard Worker //  instead.
StrEndsWith(const char * name,size_t prefix_len,const char * expected)52*6777b538SAndroid Build Coastguard Worker constexpr bool StrEndsWith(const char* name,
53*6777b538SAndroid Build Coastguard Worker                            size_t prefix_len,
54*6777b538SAndroid Build Coastguard Worker                            const char* expected) {
55*6777b538SAndroid Build Coastguard Worker   const size_t name_len = StrLen(name);
56*6777b538SAndroid Build Coastguard Worker   const size_t expected_len = StrLen(expected);
57*6777b538SAndroid Build Coastguard Worker   if (name_len != prefix_len + expected_len)
58*6777b538SAndroid Build Coastguard Worker     return false;
59*6777b538SAndroid Build Coastguard Worker   for (size_t i = 0; i < expected_len; ++i) {
60*6777b538SAndroid Build Coastguard Worker     if (name[i + prefix_len] != expected[i])
61*6777b538SAndroid Build Coastguard Worker       return false;
62*6777b538SAndroid Build Coastguard Worker   }
63*6777b538SAndroid Build Coastguard Worker   return true;
64*6777b538SAndroid Build Coastguard Worker }
65*6777b538SAndroid Build Coastguard Worker 
66*6777b538SAndroid Build Coastguard Worker #if defined(__clang__) && defined(_MSC_VER)
67*6777b538SAndroid Build Coastguard Worker static_assert(StrEndsWith(__FILE__, kStrippedPrefixLength, "base\\location.cc"),
68*6777b538SAndroid Build Coastguard Worker               "The file name does not match the expected prefix format.");
69*6777b538SAndroid Build Coastguard Worker #else
70*6777b538SAndroid Build Coastguard Worker static_assert(StrEndsWith(__FILE__, kStrippedPrefixLength, "base/location.cc"),
71*6777b538SAndroid Build Coastguard Worker               "The file name does not match the expected prefix format.");
72*6777b538SAndroid Build Coastguard Worker #endif
73*6777b538SAndroid Build Coastguard Worker 
74*6777b538SAndroid Build Coastguard Worker }  // namespace
75*6777b538SAndroid Build Coastguard Worker 
76*6777b538SAndroid Build Coastguard Worker Location::Location() = default;
77*6777b538SAndroid Build Coastguard Worker Location::Location(const Location& other) = default;
78*6777b538SAndroid Build Coastguard Worker Location::Location(Location&& other) noexcept = default;
79*6777b538SAndroid Build Coastguard Worker Location& Location::operator=(const Location& other) = default;
80*6777b538SAndroid Build Coastguard Worker 
Location(const char * file_name,const void * program_counter)81*6777b538SAndroid Build Coastguard Worker Location::Location(const char* file_name, const void* program_counter)
82*6777b538SAndroid Build Coastguard Worker     : file_name_(file_name), program_counter_(program_counter) {}
83*6777b538SAndroid Build Coastguard Worker 
Location(const char * function_name,const char * file_name,int line_number,const void * program_counter)84*6777b538SAndroid Build Coastguard Worker Location::Location(const char* function_name,
85*6777b538SAndroid Build Coastguard Worker                    const char* file_name,
86*6777b538SAndroid Build Coastguard Worker                    int line_number,
87*6777b538SAndroid Build Coastguard Worker                    const void* program_counter)
88*6777b538SAndroid Build Coastguard Worker     : function_name_(function_name),
89*6777b538SAndroid Build Coastguard Worker       file_name_(file_name),
90*6777b538SAndroid Build Coastguard Worker       line_number_(line_number),
91*6777b538SAndroid Build Coastguard Worker       program_counter_(program_counter) {
92*6777b538SAndroid Build Coastguard Worker #if !BUILDFLAG(IS_NACL)
93*6777b538SAndroid Build Coastguard Worker   // The program counter should not be null except in a default constructed
94*6777b538SAndroid Build Coastguard Worker   // (empty) Location object. This value is used for identity, so if it doesn't
95*6777b538SAndroid Build Coastguard Worker   // uniquely identify a location, things will break.
96*6777b538SAndroid Build Coastguard Worker   //
97*6777b538SAndroid Build Coastguard Worker   // The program counter isn't supported in NaCl so location objects won't work
98*6777b538SAndroid Build Coastguard Worker   // properly in that context.
99*6777b538SAndroid Build Coastguard Worker   DCHECK(program_counter);
100*6777b538SAndroid Build Coastguard Worker #endif
101*6777b538SAndroid Build Coastguard Worker }
102*6777b538SAndroid Build Coastguard Worker 
ToString() const103*6777b538SAndroid Build Coastguard Worker std::string Location::ToString() const {
104*6777b538SAndroid Build Coastguard Worker   if (has_source_info()) {
105*6777b538SAndroid Build Coastguard Worker     return std::string(function_name_) + "@" + file_name_ + ":" +
106*6777b538SAndroid Build Coastguard Worker            NumberToString(line_number_);
107*6777b538SAndroid Build Coastguard Worker   }
108*6777b538SAndroid Build Coastguard Worker   return StringPrintf("pc:%p", program_counter_);
109*6777b538SAndroid Build Coastguard Worker }
110*6777b538SAndroid Build Coastguard Worker 
WriteIntoTrace(perfetto::TracedValue context) const111*6777b538SAndroid Build Coastguard Worker void Location::WriteIntoTrace(perfetto::TracedValue context) const {
112*6777b538SAndroid Build Coastguard Worker   auto dict = std::move(context).WriteDictionary();
113*6777b538SAndroid Build Coastguard Worker   dict.Add("function_name", function_name_);
114*6777b538SAndroid Build Coastguard Worker   dict.Add("file_name", file_name_);
115*6777b538SAndroid Build Coastguard Worker   dict.Add("line_number", line_number_);
116*6777b538SAndroid Build Coastguard Worker }
117*6777b538SAndroid Build Coastguard Worker 
118*6777b538SAndroid Build Coastguard Worker #if defined(COMPILER_MSVC)
119*6777b538SAndroid Build Coastguard Worker #define RETURN_ADDRESS() _ReturnAddress()
120*6777b538SAndroid Build Coastguard Worker #elif defined(COMPILER_GCC) && !BUILDFLAG(IS_NACL)
121*6777b538SAndroid Build Coastguard Worker #define RETURN_ADDRESS() \
122*6777b538SAndroid Build Coastguard Worker   __builtin_extract_return_addr(__builtin_return_address(0))
123*6777b538SAndroid Build Coastguard Worker #else
124*6777b538SAndroid Build Coastguard Worker #define RETURN_ADDRESS() nullptr
125*6777b538SAndroid Build Coastguard Worker #endif
126*6777b538SAndroid Build Coastguard Worker 
127*6777b538SAndroid Build Coastguard Worker // static
Current(const char * function_name,const char * file_name,int line_number)128*6777b538SAndroid Build Coastguard Worker NOINLINE Location Location::Current(const char* function_name,
129*6777b538SAndroid Build Coastguard Worker                                     const char* file_name,
130*6777b538SAndroid Build Coastguard Worker                                     int line_number) {
131*6777b538SAndroid Build Coastguard Worker   return Location(function_name, file_name + kStrippedPrefixLength, line_number,
132*6777b538SAndroid Build Coastguard Worker                   RETURN_ADDRESS());
133*6777b538SAndroid Build Coastguard Worker }
134*6777b538SAndroid Build Coastguard Worker 
135*6777b538SAndroid Build Coastguard Worker //------------------------------------------------------------------------------
GetProgramCounter()136*6777b538SAndroid Build Coastguard Worker NOINLINE const void* GetProgramCounter() {
137*6777b538SAndroid Build Coastguard Worker   return RETURN_ADDRESS();
138*6777b538SAndroid Build Coastguard Worker }
139*6777b538SAndroid Build Coastguard Worker 
140*6777b538SAndroid Build Coastguard Worker }  // namespace base
141