Home | History | Annotate | Download | only in processor
      1 // Copyright (c) 2010 Google Inc.
      2 // All rights reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions are
      6 // met:
      7 //
      8 //     * Redistributions of source code must retain the above copyright
      9 // notice, this list of conditions and the following disclaimer.
     10 //     * Redistributions in binary form must reproduce the above
     11 // copyright notice, this list of conditions and the following disclaimer
     12 // in the documentation and/or other materials provided with the
     13 // distribution.
     14 //     * Neither the name of Google Inc. nor the names of its
     15 // contributors may be used to endorse or promote products derived from
     16 // this software without specific prior written permission.
     17 //
     18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29 
     30 #include <assert.h>
     31 #include <stdio.h>
     32 
     33 #include <string>
     34 
     35 #include "breakpad_googletest_includes.h"
     36 #include "common/scoped_ptr.h"
     37 #include "common/using_std_string.h"
     38 #include "google_breakpad/processor/basic_source_line_resolver.h"
     39 #include "google_breakpad/processor/code_module.h"
     40 #include "google_breakpad/processor/stack_frame.h"
     41 #include "google_breakpad/processor/memory_region.h"
     42 #include "processor/linked_ptr.h"
     43 #include "processor/logging.h"
     44 #include "processor/windows_frame_info.h"
     45 #include "processor/cfi_frame_info.h"
     46 
     47 namespace {
     48 
     49 using google_breakpad::BasicSourceLineResolver;
     50 using google_breakpad::CFIFrameInfo;
     51 using google_breakpad::CodeModule;
     52 using google_breakpad::MemoryRegion;
     53 using google_breakpad::StackFrame;
     54 using google_breakpad::WindowsFrameInfo;
     55 using google_breakpad::linked_ptr;
     56 using google_breakpad::scoped_ptr;
     57 using google_breakpad::SymbolParseHelper;
     58 
     59 class TestCodeModule : public CodeModule {
     60  public:
     61   TestCodeModule(string code_file) : code_file_(code_file) {}
     62   virtual ~TestCodeModule() {}
     63 
     64   virtual uint64_t base_address() const { return 0; }
     65   virtual uint64_t size() const { return 0xb000; }
     66   virtual string code_file() const { return code_file_; }
     67   virtual string code_identifier() const { return ""; }
     68   virtual string debug_file() const { return ""; }
     69   virtual string debug_identifier() const { return ""; }
     70   virtual string version() const { return ""; }
     71   virtual const CodeModule* Copy() const {
     72     return new TestCodeModule(code_file_);
     73   }
     74 
     75  private:
     76   string code_file_;
     77 };
     78 
     79 // A mock memory region object, for use by the STACK CFI tests.
     80 class MockMemoryRegion: public MemoryRegion {
     81   uint64_t GetBase() const { return 0x10000; }
     82   uint32_t GetSize() const { return 0x01000; }
     83   bool GetMemoryAtAddress(uint64_t address, uint8_t *value) const {
     84     *value = address & 0xff;
     85     return true;
     86   }
     87   bool GetMemoryAtAddress(uint64_t address, uint16_t *value) const {
     88     *value = address & 0xffff;
     89     return true;
     90   }
     91   bool GetMemoryAtAddress(uint64_t address, uint32_t *value) const {
     92     switch (address) {
     93       case 0x10008: *value = 0x98ecadc3; break; // saved %ebx
     94       case 0x1000c: *value = 0x878f7524; break; // saved %esi
     95       case 0x10010: *value = 0x6312f9a5; break; // saved %edi
     96       case 0x10014: *value = 0x10038;    break; // caller's %ebp
     97       case 0x10018: *value = 0xf6438648; break; // return address
     98       default: *value = 0xdeadbeef;      break; // junk
     99     }
    100     return true;
    101   }
    102   bool GetMemoryAtAddress(uint64_t address, uint64_t *value) const {
    103     *value = address;
    104     return true;
    105   }
    106   void Print() const {
    107     assert(false);
    108   }
    109 };
    110 
    111 // Verify that, for every association in ACTUAL, EXPECTED has the same
    112 // association. (That is, ACTUAL's associations should be a subset of
    113 // EXPECTED's.) Also verify that ACTUAL has associations for ".ra" and
    114 // ".cfa".
    115 static bool VerifyRegisters(
    116     const char *file, int line,
    117     const CFIFrameInfo::RegisterValueMap<uint32_t> &expected,
    118     const CFIFrameInfo::RegisterValueMap<uint32_t> &actual) {
    119   CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator a;
    120   a = actual.find(".cfa");
    121   if (a == actual.end())
    122     return false;
    123   a = actual.find(".ra");
    124   if (a == actual.end())
    125     return false;
    126   for (a = actual.begin(); a != actual.end(); a++) {
    127     CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator e =
    128       expected.find(a->first);
    129     if (e == expected.end()) {
    130       fprintf(stderr, "%s:%d: unexpected register '%s' recovered, value 0x%x\n",
    131               file, line, a->first.c_str(), a->second);
    132       return false;
    133     }
    134     if (e->second != a->second) {
    135       fprintf(stderr,
    136               "%s:%d: register '%s' recovered value was 0x%x, expected 0x%x\n",
    137               file, line, a->first.c_str(), a->second, e->second);
    138       return false;
    139     }
    140     // Don't complain if this doesn't recover all registers. Although
    141     // the DWARF spec says that unmentioned registers are undefined,
    142     // GCC uses omission to mean that they are unchanged.
    143   }
    144   return true;
    145 }
    146 
    147 
    148 static bool VerifyEmpty(const StackFrame &frame) {
    149   if (frame.function_name.empty() &&
    150       frame.source_file_name.empty() &&
    151       frame.source_line == 0)
    152     return true;
    153   return false;
    154 }
    155 
    156 static void ClearSourceLineInfo(StackFrame *frame) {
    157   frame->function_name.clear();
    158   frame->module = NULL;
    159   frame->source_file_name.clear();
    160   frame->source_line = 0;
    161 }
    162 
    163 class TestBasicSourceLineResolver : public ::testing::Test {
    164 public:
    165   void SetUp() {
    166     testdata_dir = string(getenv("srcdir") ? getenv("srcdir") : ".") +
    167                          "/src/processor/testdata";
    168   }
    169 
    170   BasicSourceLineResolver resolver;
    171   string testdata_dir;
    172 };
    173 
    174 TEST_F(TestBasicSourceLineResolver, TestLoadAndResolve)
    175 {
    176   TestCodeModule module1("module1");
    177   ASSERT_TRUE(resolver.LoadModule(&module1, testdata_dir + "/module1.out"));
    178   ASSERT_TRUE(resolver.HasModule(&module1));
    179   TestCodeModule module2("module2");
    180   ASSERT_TRUE(resolver.LoadModule(&module2, testdata_dir + "/module2.out"));
    181   ASSERT_TRUE(resolver.HasModule(&module2));
    182 
    183 
    184   StackFrame frame;
    185   scoped_ptr<WindowsFrameInfo> windows_frame_info;
    186   scoped_ptr<CFIFrameInfo> cfi_frame_info;
    187   frame.instruction = 0x1000;
    188   frame.module = NULL;
    189   resolver.FillSourceLineInfo(&frame);
    190   ASSERT_FALSE(frame.module);
    191   ASSERT_TRUE(frame.function_name.empty());
    192   ASSERT_EQ(frame.function_base, 0U);
    193   ASSERT_TRUE(frame.source_file_name.empty());
    194   ASSERT_EQ(frame.source_line, 0);
    195   ASSERT_EQ(frame.source_line_base, 0U);
    196 
    197   frame.module = &module1;
    198   resolver.FillSourceLineInfo(&frame);
    199   ASSERT_EQ(frame.function_name, "Function1_1");
    200   ASSERT_TRUE(frame.module);
    201   ASSERT_EQ(frame.module->code_file(), "module1");
    202   ASSERT_EQ(frame.function_base, 0x1000U);
    203   ASSERT_EQ(frame.source_file_name, "file1_1.cc");
    204   ASSERT_EQ(frame.source_line, 44);
    205   ASSERT_EQ(frame.source_line_base, 0x1000U);
    206   windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame));
    207   ASSERT_TRUE(windows_frame_info.get());
    208   ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_FRAME_DATA);
    209   ASSERT_FALSE(windows_frame_info->allocates_base_pointer);
    210   ASSERT_EQ(windows_frame_info->program_string,
    211             "$eip 4 + ^ = $esp $ebp 8 + = $ebp $ebp ^ =");
    212 
    213   ClearSourceLineInfo(&frame);
    214   frame.instruction = 0x800;
    215   frame.module = &module1;
    216   resolver.FillSourceLineInfo(&frame);
    217   ASSERT_TRUE(VerifyEmpty(frame));
    218   windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame));
    219   ASSERT_FALSE(windows_frame_info.get());
    220 
    221   frame.instruction = 0x1280;
    222   resolver.FillSourceLineInfo(&frame);
    223   ASSERT_EQ(frame.function_name, "Function1_3");
    224   ASSERT_TRUE(frame.source_file_name.empty());
    225   ASSERT_EQ(frame.source_line, 0);
    226   windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame));
    227   ASSERT_TRUE(windows_frame_info.get());
    228   ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_UNKNOWN);
    229   ASSERT_FALSE(windows_frame_info->allocates_base_pointer);
    230   ASSERT_TRUE(windows_frame_info->program_string.empty());
    231 
    232   frame.instruction = 0x1380;
    233   resolver.FillSourceLineInfo(&frame);
    234   ASSERT_EQ(frame.function_name, "Function1_4");
    235   ASSERT_TRUE(frame.source_file_name.empty());
    236   ASSERT_EQ(frame.source_line, 0);
    237   windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame));
    238   ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_FRAME_DATA);
    239   ASSERT_TRUE(windows_frame_info.get());
    240   ASSERT_FALSE(windows_frame_info->allocates_base_pointer);
    241   ASSERT_FALSE(windows_frame_info->program_string.empty());
    242 
    243   frame.instruction = 0x2000;
    244   windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame));
    245   ASSERT_FALSE(windows_frame_info.get());
    246 
    247   // module1 has STACK CFI records covering 3d40..3def;
    248   // module2 has STACK CFI records covering 3df0..3e9f;
    249   // check that FindCFIFrameInfo doesn't claim to find any outside those ranges.
    250   frame.instruction = 0x3d3f;
    251   frame.module = &module1;
    252   cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
    253   ASSERT_FALSE(cfi_frame_info.get());
    254 
    255   frame.instruction = 0x3e9f;
    256   frame.module = &module1;
    257   cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
    258   ASSERT_FALSE(cfi_frame_info.get());
    259 
    260   CFIFrameInfo::RegisterValueMap<uint32_t> current_registers;
    261   CFIFrameInfo::RegisterValueMap<uint32_t> caller_registers;
    262   CFIFrameInfo::RegisterValueMap<uint32_t> expected_caller_registers;
    263   MockMemoryRegion memory;
    264 
    265   // Regardless of which instruction evaluation takes place at, it
    266   // should produce the same values for the caller's registers.
    267   expected_caller_registers[".cfa"] = 0x1001c;
    268   expected_caller_registers[".ra"]  = 0xf6438648;
    269   expected_caller_registers["$ebp"] = 0x10038;
    270   expected_caller_registers["$ebx"] = 0x98ecadc3;
    271   expected_caller_registers["$esi"] = 0x878f7524;
    272   expected_caller_registers["$edi"] = 0x6312f9a5;
    273 
    274   frame.instruction = 0x3d40;
    275   frame.module = &module1;
    276   current_registers.clear();
    277   current_registers["$esp"] = 0x10018;
    278   current_registers["$ebp"] = 0x10038;
    279   current_registers["$ebx"] = 0x98ecadc3;
    280   current_registers["$esi"] = 0x878f7524;
    281   current_registers["$edi"] = 0x6312f9a5;
    282   cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
    283   ASSERT_TRUE(cfi_frame_info.get());
    284   ASSERT_TRUE(cfi_frame_info.get()
    285               ->FindCallerRegs<uint32_t>(current_registers, memory,
    286                                           &caller_registers));
    287   ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__,
    288                               expected_caller_registers, caller_registers));
    289 
    290   frame.instruction = 0x3d41;
    291   current_registers["$esp"] = 0x10014;
    292   cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
    293   ASSERT_TRUE(cfi_frame_info.get());
    294   ASSERT_TRUE(cfi_frame_info.get()
    295               ->FindCallerRegs<uint32_t>(current_registers, memory,
    296                                           &caller_registers));
    297   ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__,
    298                               expected_caller_registers, caller_registers));
    299 
    300   frame.instruction = 0x3d43;
    301   current_registers["$ebp"] = 0x10014;
    302   cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
    303   ASSERT_TRUE(cfi_frame_info.get());
    304   ASSERT_TRUE(cfi_frame_info.get()
    305               ->FindCallerRegs<uint32_t>(current_registers, memory,
    306                                           &caller_registers));
    307   VerifyRegisters(__FILE__, __LINE__,
    308                   expected_caller_registers, caller_registers);
    309 
    310   frame.instruction = 0x3d54;
    311   current_registers["$ebx"] = 0x6864f054U;
    312   cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
    313   ASSERT_TRUE(cfi_frame_info.get());
    314   ASSERT_TRUE(cfi_frame_info.get()
    315               ->FindCallerRegs<uint32_t>(current_registers, memory,
    316                                           &caller_registers));
    317   VerifyRegisters(__FILE__, __LINE__,
    318                   expected_caller_registers, caller_registers);
    319 
    320   frame.instruction = 0x3d5a;
    321   current_registers["$esi"] = 0x6285f79aU;
    322   cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
    323   ASSERT_TRUE(cfi_frame_info.get());
    324   ASSERT_TRUE(cfi_frame_info.get()
    325               ->FindCallerRegs<uint32_t>(current_registers, memory,
    326                                           &caller_registers));
    327   VerifyRegisters(__FILE__, __LINE__,
    328                   expected_caller_registers, caller_registers);
    329 
    330   frame.instruction = 0x3d84;
    331   current_registers["$edi"] = 0x64061449U;
    332   cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
    333   ASSERT_TRUE(cfi_frame_info.get());
    334   ASSERT_TRUE(cfi_frame_info.get()
    335               ->FindCallerRegs<uint32_t>(current_registers, memory,
    336                                           &caller_registers));
    337   VerifyRegisters(__FILE__, __LINE__,
    338                   expected_caller_registers, caller_registers);
    339 
    340   frame.instruction = 0x2900;
    341   frame.module = &module1;
    342   resolver.FillSourceLineInfo(&frame);
    343   ASSERT_EQ(frame.function_name, string("PublicSymbol"));
    344 
    345   frame.instruction = 0x4000;
    346   frame.module = &module1;
    347   resolver.FillSourceLineInfo(&frame);
    348   ASSERT_EQ(frame.function_name, string("LargeFunction"));
    349 
    350   frame.instruction = 0x2181;
    351   frame.module = &module2;
    352   resolver.FillSourceLineInfo(&frame);
    353   ASSERT_EQ(frame.function_name, "Function2_2");
    354   ASSERT_EQ(frame.function_base, 0x2170U);
    355   ASSERT_TRUE(frame.module);
    356   ASSERT_EQ(frame.module->code_file(), "module2");
    357   ASSERT_EQ(frame.source_file_name, "file2_2.cc");
    358   ASSERT_EQ(frame.source_line, 21);
    359   ASSERT_EQ(frame.source_line_base, 0x2180U);
    360   windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame));
    361   ASSERT_TRUE(windows_frame_info.get());
    362   ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_FRAME_DATA);
    363   ASSERT_EQ(windows_frame_info->prolog_size, 1U);
    364 
    365   frame.instruction = 0x216f;
    366   resolver.FillSourceLineInfo(&frame);
    367   ASSERT_EQ(frame.function_name, "Public2_1");
    368 
    369   ClearSourceLineInfo(&frame);
    370   frame.instruction = 0x219f;
    371   frame.module = &module2;
    372   resolver.FillSourceLineInfo(&frame);
    373   ASSERT_TRUE(frame.function_name.empty());
    374 
    375   frame.instruction = 0x21a0;
    376   frame.module = &module2;
    377   resolver.FillSourceLineInfo(&frame);
    378   ASSERT_EQ(frame.function_name, "Public2_2");
    379 }
    380 
    381 TEST_F(TestBasicSourceLineResolver, TestInvalidLoads)
    382 {
    383   TestCodeModule module3("module3");
    384   ASSERT_TRUE(resolver.LoadModule(&module3,
    385                                    testdata_dir + "/module3_bad.out"));
    386   ASSERT_TRUE(resolver.HasModule(&module3));
    387   ASSERT_TRUE(resolver.IsModuleCorrupt(&module3));
    388   TestCodeModule module4("module4");
    389   ASSERT_TRUE(resolver.LoadModule(&module4,
    390                                    testdata_dir + "/module4_bad.out"));
    391   ASSERT_TRUE(resolver.HasModule(&module4));
    392   ASSERT_TRUE(resolver.IsModuleCorrupt(&module4));
    393   TestCodeModule module5("module5");
    394   ASSERT_FALSE(resolver.LoadModule(&module5,
    395                                    testdata_dir + "/invalid-filename"));
    396   ASSERT_FALSE(resolver.HasModule(&module5));
    397   TestCodeModule invalidmodule("invalid-module");
    398   ASSERT_FALSE(resolver.HasModule(&invalidmodule));
    399 }
    400 
    401 TEST_F(TestBasicSourceLineResolver, TestUnload)
    402 {
    403   TestCodeModule module1("module1");
    404   ASSERT_FALSE(resolver.HasModule(&module1));
    405   ASSERT_TRUE(resolver.LoadModule(&module1, testdata_dir + "/module1.out"));
    406   ASSERT_TRUE(resolver.HasModule(&module1));
    407   resolver.UnloadModule(&module1);
    408   ASSERT_FALSE(resolver.HasModule(&module1));
    409   ASSERT_TRUE(resolver.LoadModule(&module1, testdata_dir + "/module1.out"));
    410   ASSERT_TRUE(resolver.HasModule(&module1));
    411 }
    412 
    413 // Test parsing of valid FILE lines.  The format is:
    414 // FILE <id> <filename>
    415 TEST(SymbolParseHelper, ParseFileValid) {
    416   long index;
    417   char *filename;
    418 
    419   char kTestLine[] = "FILE 1 file name";
    420   ASSERT_TRUE(SymbolParseHelper::ParseFile(kTestLine, &index, &filename));
    421   EXPECT_EQ(1, index);
    422   EXPECT_EQ("file name", string(filename));
    423 
    424   // 0 is a valid index.
    425   char kTestLine1[] = "FILE 0 file name";
    426   ASSERT_TRUE(SymbolParseHelper::ParseFile(kTestLine1, &index, &filename));
    427   EXPECT_EQ(0, index);
    428   EXPECT_EQ("file name", string(filename));
    429 }
    430 
    431 // Test parsing of invalid FILE lines.  The format is:
    432 // FILE <id> <filename>
    433 TEST(SymbolParseHelper, ParseFileInvalid) {
    434   long index;
    435   char *filename;
    436 
    437   // Test missing file name.
    438   char kTestLine[] = "FILE 1 ";
    439   ASSERT_FALSE(SymbolParseHelper::ParseFile(kTestLine, &index, &filename));
    440 
    441   // Test bad index.
    442   char kTestLine1[] = "FILE x1 file name";
    443   ASSERT_FALSE(SymbolParseHelper::ParseFile(kTestLine1, &index, &filename));
    444 
    445   // Test large index.
    446   char kTestLine2[] = "FILE 123123123123123123123123 file name";
    447   ASSERT_FALSE(SymbolParseHelper::ParseFile(kTestLine2, &index, &filename));
    448 
    449   // Test negative index.
    450   char kTestLine3[] = "FILE -2 file name";
    451   ASSERT_FALSE(SymbolParseHelper::ParseFile(kTestLine3, &index, &filename));
    452 }
    453 
    454 // Test parsing of valid FUNC lines.  The format is:
    455 // FUNC <address> <size> <stack_param_size> <name>
    456 TEST(SymbolParseHelper, ParseFunctionValid) {
    457   uint64_t address;
    458   uint64_t size;
    459   long stack_param_size;
    460   char *name;
    461 
    462   char kTestLine[] = "FUNC 1 2 3 function name";
    463   ASSERT_TRUE(SymbolParseHelper::ParseFunction(kTestLine, &address, &size,
    464                                                &stack_param_size, &name));
    465   EXPECT_EQ(1ULL, address);
    466   EXPECT_EQ(2ULL, size);
    467   EXPECT_EQ(3, stack_param_size);
    468   EXPECT_EQ("function name", string(name));
    469 
    470   // Test hex address, size, and param size.
    471   char kTestLine1[] = "FUNC a1 a2 a3 function name";
    472   ASSERT_TRUE(SymbolParseHelper::ParseFunction(kTestLine1, &address, &size,
    473                                                &stack_param_size, &name));
    474   EXPECT_EQ(0xa1ULL, address);
    475   EXPECT_EQ(0xa2ULL, size);
    476   EXPECT_EQ(0xa3, stack_param_size);
    477   EXPECT_EQ("function name", string(name));
    478 
    479   char kTestLine2[] = "FUNC 0 0 0 function name";
    480   ASSERT_TRUE(SymbolParseHelper::ParseFunction(kTestLine2, &address, &size,
    481                                                &stack_param_size, &name));
    482   EXPECT_EQ(0ULL, address);
    483   EXPECT_EQ(0ULL, size);
    484   EXPECT_EQ(0, stack_param_size);
    485   EXPECT_EQ("function name", string(name));
    486 }
    487 
    488 // Test parsing of invalid FUNC lines.  The format is:
    489 // FUNC <address> <size> <stack_param_size> <name>
    490 TEST(SymbolParseHelper, ParseFunctionInvalid) {
    491   uint64_t address;
    492   uint64_t size;
    493   long stack_param_size;
    494   char *name;
    495 
    496   // Test missing function name.
    497   char kTestLine[] = "FUNC 1 2 3 ";
    498   ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine, &address, &size,
    499                                                 &stack_param_size, &name));
    500   // Test bad address.
    501   char kTestLine1[] = "FUNC 1z 2 3 function name";
    502   ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine1, &address, &size,
    503                                                 &stack_param_size, &name));
    504   // Test large address.
    505   char kTestLine2[] = "FUNC 123123123123123123123123123 2 3 function name";
    506   ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine2, &address, &size,
    507                                                 &stack_param_size, &name));
    508   // Test bad size.
    509   char kTestLine3[] = "FUNC 1 z2 3 function name";
    510   ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine3, &address, &size,
    511                                                 &stack_param_size, &name));
    512   // Test large size.
    513   char kTestLine4[] = "FUNC 1 231231231231231231231231232 3 function name";
    514   ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine4, &address, &size,
    515                                                 &stack_param_size, &name));
    516   // Test bad param size.
    517   char kTestLine5[] = "FUNC 1 2 3z function name";
    518   ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine5, &address, &size,
    519                                                 &stack_param_size, &name));
    520   // Test large param size.
    521   char kTestLine6[] = "FUNC 1 2 312312312312312312312312323 function name";
    522   ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine6, &address, &size,
    523                                                 &stack_param_size, &name));
    524   // Negative param size.
    525   char kTestLine7[] = "FUNC 1 2 -5 function name";
    526   ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine7, &address, &size,
    527                                                 &stack_param_size, &name));
    528 }
    529 
    530 // Test parsing of valid lines.  The format is:
    531 // <address> <size> <line number> <source file id>
    532 TEST(SymbolParseHelper, ParseLineValid) {
    533   uint64_t address;
    534   uint64_t size;
    535   long line_number;
    536   long source_file;
    537 
    538   char kTestLine[] = "1 2 3 4";
    539   ASSERT_TRUE(SymbolParseHelper::ParseLine(kTestLine, &address, &size,
    540                                            &line_number, &source_file));
    541   EXPECT_EQ(1ULL, address);
    542   EXPECT_EQ(2ULL, size);
    543   EXPECT_EQ(3, line_number);
    544   EXPECT_EQ(4, source_file);
    545 
    546   // Test hex size and address.
    547   char kTestLine1[] = "a1 a2 3 4  // some comment";
    548   ASSERT_TRUE(SymbolParseHelper::ParseLine(kTestLine1, &address, &size,
    549                                            &line_number, &source_file));
    550   EXPECT_EQ(0xa1ULL, address);
    551   EXPECT_EQ(0xa2ULL, size);
    552   EXPECT_EQ(3, line_number);
    553   EXPECT_EQ(4, source_file);
    554 
    555   // 0 is a valid line number.
    556   char kTestLine2[] = "a1 a2 0 4  // some comment";
    557   ASSERT_TRUE(SymbolParseHelper::ParseLine(kTestLine2, &address, &size,
    558                                            &line_number, &source_file));
    559   EXPECT_EQ(0xa1ULL, address);
    560   EXPECT_EQ(0xa2ULL, size);
    561   EXPECT_EQ(0, line_number);
    562   EXPECT_EQ(4, source_file);
    563 }
    564 
    565 // Test parsing of invalid lines.  The format is:
    566 // <address> <size> <line number> <source file id>
    567 TEST(SymbolParseHelper, ParseLineInvalid) {
    568   uint64_t address;
    569   uint64_t size;
    570   long line_number;
    571   long source_file;
    572 
    573   // Test missing source file id.
    574   char kTestLine[] = "1 2 3";
    575   ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine, &address, &size,
    576                                             &line_number, &source_file));
    577   // Test bad address.
    578   char kTestLine1[] = "1z 2 3 4";
    579   ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine1, &address, &size,
    580                                             &line_number, &source_file));
    581   // Test large address.
    582   char kTestLine2[] = "123123123123123123123123 2 3 4";
    583   ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine2, &address, &size,
    584                                             &line_number, &source_file));
    585   // Test bad size.
    586   char kTestLine3[] = "1 z2 3 4";
    587   ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine3, &address, &size,
    588                                             &line_number, &source_file));
    589   // Test large size.
    590   char kTestLine4[] = "1 123123123123123123123123 3 4";
    591   ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine4, &address, &size,
    592                                             &line_number, &source_file));
    593   // Test bad line number.
    594   char kTestLine5[] = "1 2 z3 4";
    595   ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine5, &address, &size,
    596                                             &line_number, &source_file));
    597   // Test negative line number.
    598   char kTestLine6[] = "1 2 -1 4";
    599   ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine6, &address, &size,
    600                                             &line_number, &source_file));
    601   // Test large line number.
    602   char kTestLine7[] = "1 2 123123123123123123123 4";
    603   ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine7, &address, &size,
    604                                             &line_number, &source_file));
    605   // Test bad source file id.
    606   char kTestLine8[] = "1 2 3 f";
    607   ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine8, &address, &size,
    608                                             &line_number, &source_file));
    609 }
    610 
    611 // Test parsing of valid PUBLIC lines.  The format is:
    612 // PUBLIC <address> <stack_param_size> <name>
    613 TEST(SymbolParseHelper, ParsePublicSymbolValid) {
    614   uint64_t address;
    615   long stack_param_size;
    616   char *name;
    617 
    618   char kTestLine[] = "PUBLIC 1 2 3";
    619   ASSERT_TRUE(SymbolParseHelper::ParsePublicSymbol(kTestLine, &address,
    620                                                    &stack_param_size, &name));
    621   EXPECT_EQ(1ULL, address);
    622   EXPECT_EQ(2, stack_param_size);
    623   EXPECT_EQ("3", string(name));
    624 
    625   // Test hex size and address.
    626   char kTestLine1[] = "PUBLIC a1 a2 function name";
    627   ASSERT_TRUE(SymbolParseHelper::ParsePublicSymbol(kTestLine1, &address,
    628                                                    &stack_param_size, &name));
    629   EXPECT_EQ(0xa1ULL, address);
    630   EXPECT_EQ(0xa2, stack_param_size);
    631   EXPECT_EQ("function name", string(name));
    632 
    633   // Test 0 is a valid address.
    634   char kTestLine2[] = "PUBLIC 0 a2 function name";
    635   ASSERT_TRUE(SymbolParseHelper::ParsePublicSymbol(kTestLine2, &address,
    636                                                    &stack_param_size, &name));
    637   EXPECT_EQ(0ULL, address);
    638   EXPECT_EQ(0xa2, stack_param_size);
    639   EXPECT_EQ("function name", string(name));
    640 }
    641 
    642 // Test parsing of invalid PUBLIC lines.  The format is:
    643 // PUBLIC <address> <stack_param_size> <name>
    644 TEST(SymbolParseHelper, ParsePublicSymbolInvalid) {
    645   uint64_t address;
    646   long stack_param_size;
    647   char *name;
    648 
    649   // Test missing source function name.
    650   char kTestLine[] = "PUBLIC 1 2 ";
    651   ASSERT_FALSE(SymbolParseHelper::ParsePublicSymbol(kTestLine, &address,
    652                                                     &stack_param_size, &name));
    653   // Test bad address.
    654   char kTestLine1[] = "PUBLIC 1z 2 3";
    655   ASSERT_FALSE(SymbolParseHelper::ParsePublicSymbol(kTestLine1, &address,
    656                                                     &stack_param_size, &name));
    657   // Test large address.
    658   char kTestLine2[] = "PUBLIC 123123123123123123123123 2 3";
    659   ASSERT_FALSE(SymbolParseHelper::ParsePublicSymbol(kTestLine2, &address,
    660                                                     &stack_param_size, &name));
    661   // Test bad param stack size.
    662   char kTestLine3[] = "PUBLIC 1 z2 3";
    663   ASSERT_FALSE(SymbolParseHelper::ParsePublicSymbol(kTestLine3, &address,
    664                                                     &stack_param_size, &name));
    665   // Test large param stack size.
    666   char kTestLine4[] = "PUBLIC 1 123123123123123123123123123 3";
    667   ASSERT_FALSE(SymbolParseHelper::ParsePublicSymbol(kTestLine4, &address,
    668                                                     &stack_param_size, &name));
    669   // Test negative param stack size.
    670   char kTestLine5[] = "PUBLIC 1 -5 3";
    671   ASSERT_FALSE(SymbolParseHelper::ParsePublicSymbol(kTestLine5, &address,
    672                                                     &stack_param_size, &name));
    673 }
    674 
    675 }  // namespace
    676 
    677 int main(int argc, char *argv[]) {
    678   ::testing::InitGoogleTest(&argc, argv);
    679   return RUN_ALL_TESTS();
    680 }
    681