Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  dwarf_test.cc

  Sprache: C
 

/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#include "dwarf_test.h"

#include "dwarf/debug_frame_opcode_writer.h"
#include "dwarf/debug_info_entry_writer.h"
#include "dwarf/debug_line_opcode_writer.h"
#include "dwarf/dwarf_constants.h"
#include "dwarf/headers.h"
#include "gtest/gtest.h"

namespace art HIDDEN {
namespace dwarf {

// Run the tests only on host since we need objdump.
#ifndef ART_TARGET_ANDROID

TEST_F(DwarfTest, DebugFrame) {
  const InstructionSet isa = InstructionSet::kX86;
  const bool is64bit = Is64BitInstructionSet(isa);

  // Pick offset value which would catch Uleb vs Sleb errors.
  const int offset = 40000;
  ASSERT_EQ(UnsignedLeb128Size(offset / 4), 2u);
  ASSERT_EQ(SignedLeb128Size(offset / 4), 3u);
  const Reg reg(6);

  // Test the opcodes in the order mentioned in the spec.
  // There are usually several encoding variations of each opcode.
  DebugFrameOpCodeWriter<> opcodes;
  DW_CHECK(".debug_frame contents:");
  DW_CHECK("FDE");
  DW_CHECK_NEXT("DWARF32");
  int pc = 0;
  for (int i : {010x3F, 0x40, 0xFF, 0x100, 0xFFFF, 0x10000}) {
    pc += i;
    opcodes.AdvancePC(pc);
  }
  DW_CHECK_NEXT("DW_CFA_advance_loc: 1");
  DW_CHECK_NEXT("DW_CFA_advance_loc: 63");
  DW_CHECK_NEXT("DW_CFA_advance_loc1: 64");
  DW_CHECK_NEXT("DW_CFA_advance_loc1: 255");
  DW_CHECK_NEXT("DW_CFA_advance_loc2: 256");
  DW_CHECK_NEXT("DW_CFA_advance_loc2: 65535");
  DW_CHECK_NEXT("DW_CFA_advance_loc4: 65536");
  opcodes.DefCFA(reg, offset);
  DW_CHECK_NEXT("DW_CFA_def_cfa: ESI +40000");
  opcodes.DefCFA(reg, -offset);
  DW_CHECK_NEXT("DW_CFA_def_cfa_sf: ESI -40000");
  opcodes.DefCFARegister(reg);
  DW_CHECK_NEXT("DW_CFA_def_cfa_register: ESI");
  opcodes.DefCFAOffset(offset);
  DW_CHECK_NEXT("DW_CFA_def_cfa_offset: +40000");
  opcodes.DefCFAOffset(-offset);
  DW_CHECK_NEXT("DW_CFA_def_cfa_offset_sf: -40000");
  uint8_t expr[] = { /*nop*/ 0x96 };
  opcodes.DefCFAExpression(expr, arraysize(expr));
  DW_CHECK_NEXT("DW_CFA_def_cfa_expression: DW_OP_nop");
  opcodes.Undefined(reg);
  DW_CHECK_NEXT("DW_CFA_undefined: ESI");
  opcodes.SameValue(reg);
  DW_CHECK_NEXT("DW_CFA_same_value: ESI");
  opcodes.Offset(Reg(0x3F), -offset);
  DW_CHECK_NEXT("DW_CFA_offset: reg63 -40000");
  opcodes.Offset(Reg(0x40), -offset);
  DW_CHECK_NEXT("DW_CFA_offset_extended: reg64 -40000");
  opcodes.Offset(Reg(0x40), offset);
  DW_CHECK_NEXT("DW_CFA_offset_extended_sf: reg64 40000");
  opcodes.ValOffset(reg, -offset);
  DW_CHECK_NEXT("DW_CFA_val_offset: ESI -40000");
  opcodes.ValOffset(reg, offset);
  DW_CHECK_NEXT("DW_CFA_val_offset_sf: ESI 40000");
  opcodes.Register(reg, Reg(1));
  DW_CHECK_NEXT("DW_CFA_register: ESI ECX");
  opcodes.Expression(reg, expr, arraysize(expr));
  DW_CHECK_NEXT("DW_CFA_expression: ESI DW_OP_nop");
  opcodes.ValExpression(reg, expr, arraysize(expr));
  DW_CHECK_NEXT("DW_CFA_val_expression: ESI DW_OP_nop");
  opcodes.Restore(Reg(0x3F));
  DW_CHECK_NEXT("DW_CFA_restore: reg63");
  opcodes.Restore(Reg(0x40));
  DW_CHECK_NEXT("DW_CFA_restore_extended: reg64");
  opcodes.Restore(reg);
  DW_CHECK_NEXT("DW_CFA_restore: ESI");
  opcodes.RememberState();
  DW_CHECK_NEXT("DW_CFA_remember_state:");
  opcodes.RestoreState();
  DW_CHECK_NEXT("DW_CFA_restore_state:");
  opcodes.Nop();
  DW_CHECK_NEXT("DW_CFA_nop:");

  // Also test helpers.
  opcodes.DefCFA(Reg(4), 100);  // ESP
  DW_CHECK_NEXT("DW_CFA_def_cfa: ESP +100");
  opcodes.AdjustCFAOffset(8);
  DW_CHECK_NEXT("DW_CFA_def_cfa_offset: +108");
  opcodes.RelOffset(Reg(0), 0);  // push R0
  DW_CHECK_NEXT("DW_CFA_offset: EAX -108");
  opcodes.RelOffset(Reg(1), 4);  // push R1
  DW_CHECK_NEXT("DW_CFA_offset: ECX -104");
  opcodes.RelOffsetForMany(Reg(2), 81 | (1 << 3), 4);  // push R2 and R5
  DW_CHECK_NEXT("DW_CFA_offset: EDX -100");
  DW_CHECK_NEXT("DW_CFA_offset: EBP -96");
  opcodes.RestoreMany(Reg(2), 1 | (1 << 3));  // pop R2 and R5
  DW_CHECK_NEXT("DW_CFA_restore: EDX");
  DW_CHECK_NEXT("DW_CFA_restore: EBP");

  DebugFrameOpCodeWriter<> initial_opcodes;
  WriteCIE(is64bit, Reg(is64bit ? 16 : 8), initial_opcodes, &debug_frame_data_);
  WriteFDE(is64bit,
           /* cie_pointer= */ 0,
           0x01000000,
           0x01000000,
           ArrayRef<const uint8_t>(*opcodes.data()),
           &debug_frame_data_);

  CheckObjdumpOutput(isa, "-debug-frame");
}

TEST_F(DwarfTest, DISABLED_DebugFrame64) {
  const InstructionSet isa = InstructionSet::kX86_64;
  const bool is64bit = Is64BitInstructionSet(isa);
  DebugFrameOpCodeWriter<> initial_opcodes;
  WriteCIE(is64bit, Reg(16), initial_opcodes, &debug_frame_data_);
  DebugFrameOpCodeWriter<> opcodes;
  DW_CHECK(".debug_frame contents:");
  WriteFDE(is64bit,
           /* cie_pointer= */ 0,
           0x0100000000000000,
           0x0200000000000000,
           ArrayRef<const uint8_t>(*opcodes.data()),
           &debug_frame_data_);
  DW_CHECK("FDE cie=00000000 pc=100000000000000..300000000000000");

  CheckObjdumpOutput(isa, "-debug-frame");
}

// Test x86_64 register mapping. It is the only non-trivial architecture.
// ARM and X86 have: dwarf_reg = art_reg + constant.
TEST_F(DwarfTest, x86_64_RegisterMapping) {
  const InstructionSet isa = InstructionSet::kX86_64;
  const bool is64bit = Is64BitInstructionSet(isa);
  DebugFrameOpCodeWriter<> opcodes;
  DW_CHECK(".debug_frame contents:");
  for (int i = 0; i < 16; i++) {
    opcodes.RelOffset(Reg::X86_64Core(i), 0);
  }
  DW_CHECK("FDE");
  DW_CHECK_NEXT("DWARF32");
  DW_CHECK_NEXT("DW_CFA_offset: RAX 0");
  DW_CHECK_NEXT("DW_CFA_offset: RCX 0");
  DW_CHECK_NEXT("DW_CFA_offset: RDX 0");
  DW_CHECK_NEXT("DW_CFA_offset: RBX 0");
  DW_CHECK_NEXT("DW_CFA_offset: RSP 0");
  DW_CHECK_NEXT("DW_CFA_offset: RBP 0");
  DW_CHECK_NEXT("DW_CFA_offset: RSI 0");
  DW_CHECK_NEXT("DW_CFA_offset: RDI 0");
  DW_CHECK_NEXT("DW_CFA_offset: R8 0");
  DW_CHECK_NEXT("DW_CFA_offset: R9 0");
  DW_CHECK_NEXT("DW_CFA_offset: R10 0");
  DW_CHECK_NEXT("DW_CFA_offset: R11 0");
  DW_CHECK_NEXT("DW_CFA_offset: R12 0");
  DW_CHECK_NEXT("DW_CFA_offset: R13 0");
  DW_CHECK_NEXT("DW_CFA_offset: R14 0");
  DW_CHECK_NEXT("DW_CFA_offset: R15 0");

  DebugFrameOpCodeWriter<> initial_opcodes;
  WriteCIE(is64bit, Reg(16), initial_opcodes, &debug_frame_data_);
  WriteFDE(is64bit,
           /* cie_pointer= */ 0,
           0x0100000000000000,
           0x0200000000000000,
           ArrayRef<const uint8_t>(*opcodes.data()),
           &debug_frame_data_);

  CheckObjdumpOutput(isa, "-debug-frame");
}

TEST_F(DwarfTest, DebugLine) {
  const InstructionSet isa = InstructionSet::kX86;
  const bool is64bit = Is64BitInstructionSet(isa);
  const int code_factor_bits = 1;
  DebugLineOpCodeWriter<> opcodes(is64bit, code_factor_bits);
  DW_CHECK(".debug_line contents:");

  std::vector<std::string> include_directories;
  include_directories.push_back("/path/to/source");
  DW_CHECK("include_directories[  1] = \"/path/to/source\"");

  std::vector<FileEntry> files {
    { "file0.c"010002000 },
    { "file1.c"110002000 },
    { "file2.c"110002000 },
  };
  DW_CHECK_NEXT("file_names[  1]:");
  DW_CHECK_NEXT("           name: \"file0.c\"");
  DW_CHECK_NEXT("      dir_index: 0");
  DW_CHECK_NEXT("       mod_time: 0x000003e8");
  DW_CHECK_NEXT("         length: 0x000007d0");
  DW_CHECK_NEXT("file_names[  2]:");
  DW_CHECK_NEXT("           name: \"file1.c\"");
  DW_CHECK_NEXT("      dir_index: 1");
  DW_CHECK_NEXT("       mod_time: 0x000003e8");
  DW_CHECK_NEXT("         length: 0x000007d0");
  DW_CHECK_NEXT("file_names[  3]:");
  DW_CHECK_NEXT("           name: \"file2.c\"");
  DW_CHECK_NEXT("      dir_index: 1");
  DW_CHECK_NEXT("       mod_time: 0x000003e8");
  DW_CHECK_NEXT("         length: 0x000007d0");

  opcodes.SetAddress(0x01000000);
  opcodes.SetIsStmt(true);
  opcodes.AddRow();
  opcodes.AdvancePC(0x01000100);
  opcodes.SetFile(2);
  opcodes.AdvanceLine(3);
  opcodes.SetColumn(4);
  opcodes.SetIsStmt(false);
  opcodes.SetBasicBlock();
  opcodes.SetPrologueEnd();
  opcodes.SetEpilogueBegin();
  opcodes.SetISA(5);
  opcodes.EndSequence();
  opcodes.DefineFile("file.c"010002000);
  DW_CHECK_NEXT("Address            Line   Column File   ISA Discriminator OpIndex Flags");
  DW_CHECK_NEXT("------------------ ------ ------ ------ --- ------------- ------- -------------");
  DW_CHECK_NEXT("0x0000000001000000      1      0      1   0             0       0  is_stmt");
  DW_CHECK_NEXT("0x0000000001000100      3      4      2   5             0       0  basic_block prologue_end epilogue_begin end_sequence");

  WriteDebugLineTable(include_directories, files, opcodes, &debug_line_data_);

  CheckObjdumpOutput(isa, "-debug-line");
}

// DWARF has special one byte codes which advance PC and line at the same time.
TEST_F(DwarfTest, DebugLineSpecialOpcodes) {
  const InstructionSet isa = InstructionSet::kX86;
  const bool is64bit = Is64BitInstructionSet(isa);
  const int code_factor_bits = 1;
  uint32_t pc = 0x01000000;
  int line = 1;
  DebugLineOpCodeWriter<> opcodes(is64bit, code_factor_bits);
  opcodes.SetAddress(pc);
  size_t num_rows = 0;
  DW_CHECK(".debug_line contents:");
  DW_CHECK("file_names[  1]:");
  DW_CHECK("           name: \"file.c\"");
  DW_CHECK("Address            Line   Column File   ISA Discriminator OpIndex Flags");
  DW_CHECK("------------------ ------ ------ ------ --- ------------- ------- -------------");
  for (int addr_delta = 0; addr_delta < 80; addr_delta += 2) {
    for (int line_delta = 16; line_delta >= -16; --line_delta) {
      pc += addr_delta;
      line += line_delta;
      opcodes.AddRow(pc, line);
      num_rows++;
      ASSERT_EQ(opcodes.CurrentAddress(), pc);
      ASSERT_EQ(opcodes.CurrentLine(), line);
      char expected[1024];
      sprintf(expected, "0x%016x %6i      0      1   0             0       0", pc, line);
      DW_CHECK_NEXT(expected);
    }
  }
  opcodes.EndSequence();
  EXPECT_LT(opcodes.data()->size(), num_rows * 3);

  std::vector<std::string> directories;
  std::vector<FileEntry> files = { { "file.c"010002000 } };
  WriteDebugLineTable(directories, files, opcodes, &debug_line_data_);

  CheckObjdumpOutput(isa, "-debug-line");
}

TEST_F(DwarfTest, DebugInfo) {
  const InstructionSet isa = InstructionSet::kX86;
  const bool is64bit = Is64BitInstructionSet(isa);

  DebugAbbrevWriter<> debug_abbrev(&debug_abbrev_data_);
  DW_CHECK(".debug_abbrev contents:");
  DW_CHECK_NEXT("Abbrev table for offset: 0x00000000");
  DW_CHECK_NEXT("[1] DW_TAG_compile_unit DW_CHILDREN_yes");
  DW_CHECK_NEXT(" DW_AT_producer DW_FORM_strp");
  DW_CHECK_NEXT(" DW_AT_low_pc DW_FORM_addr");
  DW_CHECK_NEXT(" DW_AT_high_pc DW_FORM_addr");
  DW_CHECK_NEXT("[2] DW_TAG_subprogram DW_CHILDREN_no");
  DW_CHECK_NEXT(" DW_AT_name DW_FORM_strp");
  DW_CHECK_NEXT(" DW_AT_low_pc DW_FORM_addr");
  DW_CHECK_NEXT(" DW_AT_high_pc DW_FORM_addr");
  DW_CHECK_NEXT("[3] DW_TAG_compile_unit DW_CHILDREN_no");

  DebugInfoEntryWriter<> info(is64bit, &debug_abbrev);
  DW_CHECK(".debug_info contents:");
  info.StartTag(dwarf::DW_TAG_compile_unit);
  DW_CHECK_NEXT("Compile Unit: length = 0x00000030, format = DWARF32, version = 0x0004, abbr_offset = 0x0000, addr_size = 0x04");
  DW_CHECK_NEXT("DW_TAG_compile_unit");
  info.WriteStrp(dwarf::DW_AT_producer, "Compiler name", &debug_str_data_);
  DW_CHECK_NEXT("  DW_AT_producer (\"Compiler name\")");
  info.WriteAddr(dwarf::DW_AT_low_pc, 0x01000000);
  DW_CHECK_NEXT("  DW_AT_low_pc (0x01000000)");
  info.WriteAddr(dwarf::DW_AT_high_pc, 0x02000000);
  DW_CHECK_NEXT("  DW_AT_high_pc (0x02000000)");
  info.StartTag(dwarf::DW_TAG_subprogram);
  DW_CHECK_NEXT("  DW_TAG_subprogram");
  info.WriteStrp(dwarf::DW_AT_name, "Foo", &debug_str_data_);
  DW_CHECK_NEXT("    DW_AT_name (\"Foo\")");
  info.WriteAddr(dwarf::DW_AT_low_pc, 0x01010000);
  DW_CHECK_NEXT("    DW_AT_low_pc (0x01010000)");
  info.WriteAddr(dwarf::DW_AT_high_pc, 0x01020000);
  DW_CHECK_NEXT("    DW_AT_high_pc (0x01020000)");
  info.EndTag();  // DW_TAG_subprogram
  info.StartTag(dwarf::DW_TAG_subprogram);
  DW_CHECK_NEXT("  DW_TAG_subprogram");
  info.WriteStrp(dwarf::DW_AT_name, "Bar", &debug_str_data_);
  DW_CHECK_NEXT("    DW_AT_name (\"Bar\")");
  info.WriteAddr(dwarf::DW_AT_low_pc, 0x01020000);
  DW_CHECK_NEXT("    DW_AT_low_pc (0x01020000)");
  info.WriteAddr(dwarf::DW_AT_high_pc, 0x01030000);
  DW_CHECK_NEXT("    DW_AT_high_pc (0x01030000)");
  info.EndTag();  // DW_TAG_subprogram
  info.EndTag();  // DW_TAG_compile_unit
  DW_CHECK_NEXT("  NULL");
  // Test that previous list was properly terminated and empty children.
  info.StartTag(dwarf::DW_TAG_compile_unit);
  info.EndTag();  // DW_TAG_compile_unit

  dwarf::WriteDebugInfoCU(/* debug_abbrev_offset= */ 0, info, &debug_info_data_);

  CheckObjdumpOutput(isa, "-debug-info -debug-abbrev");
}

#endif  // ART_TARGET_ANDROID

}  // namespace dwarf
}  // namespace art

Messung V0.5 in Prozent
C=89 H=93 G=90

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet am  2026-06-29) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik