【问题标题】:GDB bit position bit-valuesGDB 位位置位值
【发布时间】:2018-05-09 15:46:48
【问题描述】:

我正在尝试使用 GDB 中的 ARM .elf 输出来确定地址值和大小。 使用通常的 p& 和 print 函数,我可以确定大多数地址和变量大小,但我无法确定变量是否为 bitValue。

举个例子:

typedef struct
{
  bool_t start;
  bool_t running :1;
  bool_t objectpoolUsable :1;
  bool_t ready :1;
  bool_t test :1;
  bool_t stop :1;
  uint8_t defaultMachine;
}bitFieldTest;

bitFieldTest bitValues;

当向 GDB 询问“bitValues.ready”或“bitValues.running”的地址时,它会返回相同的地址(因为它使用相同的地址),但不会给我位位置。我也不知道它是否真的是一个位值或只是一个占用 uint8_t 空间的布尔值。

澄清我需要做什么:只给 GDB 一个名称,可能是一个 bitValue,然后返回正确的地址和类型。如果这个类型是bitValue,我需要找到位位置。对于非位值,这可以正常工作,位值现在会造成麻烦。

GDB 能否提供某种输出来解决这个问题?

【问题讨论】:

  • 实际底层类型取决于bool_t,它是什么?不,没有办法获得位位置。哦,如果每个位都是一个完整的uint8_t,那么每个位肯定会有自己的地址,而不是像现在这样共享。
  • bool_t 是无符号字符。而且,是的,这很明显,关键是我必须只使用 1 个变量来知道它,而不是使用所有变量并检查双打..
  • C 语言规范保证在位域中设置一个位只会设置该位。编译器的具体实现方式并不重要,但我猜,在更大的类型中使用实际位是很常见的(考虑到两位使用相同的地址,这似乎是您的编译器实现,因为它们是单个位更大的类型)。并且回答你的问题,你想要什么是不可能的,没有支持它。您可以相信,如果您在位域中有位,它将被正确处理。

标签: c gdb arm elf


【解决方案1】:

无法使用 gdb 表达式 API 直接获取此信息。这并没有什么深层次的原因——当然 gdb 知道位的位置——但这是 gdb 表达式模仿被调试的语言这一事实​​的结果,而且只是没有人费心去暴露它。由于我以前从未听说有人想要这个,我认为可以肯定地说这是一个罕见的请求。

该信息可通过 gdb 的 Python API 获得。特别是,如果您遍历一个类型的字段,Field 对象将有一个 bitpos 成员,该成员具有数据的位偏移量。请注意,偏移量是从封闭的struct 开始的。

用 Python 编写一个打印此信息的新命令将是一件相对简单的事情。

【讨论】:

    【解决方案2】:

    我自己已经解决了这个问题。 由于我不知道如何,并且似乎没有直接的方法来返回位位置,可以通过询问 GDB 的多个地址来计算。

    使用 p& 命令可以确定变量的地址,但不能确定变量的位域或位位置。 通过在一个struct上使用GDB的print命令,我需要的bitValue的位置,它会返回这个struct中所有可用的值,例如:

    我正在寻找 bitField:MachineToUi.tramlining.sensorBoutAdvance

    MachineToUi 将返回以下内容:

    $1 = {speedPls = {present = 0 '\000', time = 0, count = 0, noPulseCount = 0, 
    value = 0, calDist = 0, calPulses = 0,END DATA  ALL DATA: sampleTime = 0}, output = {
    trackMarkerL = 0 '\000', trackMarkerR = 0 '\000', 
    workingLights = 0 '\000', foldingFrame = 0 '\000', 
    tramlineShutoffL1 = 0 '\000', tramlineShutoffR1 = 0 '\000'}, input = {
    fanPpm = 0, workswitch1 = 0 '\000', workswitch2 = 0 '\000', 
    speedSensor = 0 '\000', fanSensor = 0 '\000', meteringEncL = 0 '\000', 
    motorEncL = 0 '\000', trackMarkerL = 0 '\000', trackMarkerR = 0 '\000', 
    lowLvlHopperL = 0 '\000', venturiFlapL = 0 '\000', 
    calButtonL = 0 '\000'}, hssoOutput = HSSO_IDLE, tramlining = {
    active = 0 '\000', restoreCfg = 0 '\000', updateCfg = 0 '\000', 
    boutAdvance = 0 '\000', boutDecrement = 0 '\000', 
    noTramlineIncDec = 0 '\000', displaySfks = 0 '\000', 
    sensorBoutAdvance = 0 '\000', bout = 0 '\000'}, tramlineLeft = 0 '\000', 
    tramlineRight = 0 '\000', diagOutputs = '\000' <repeats 11 times>, 
    markerAutoDown = 0 '\000', fanRpm = 0, fanOffTime = 0, speed = 0, 
    fsAlarmSensorNr = 0 '\000', fsAlarmDisconnectedSensorNr = 0 '\000', 
    fsAlarmType = 0 '\000', seeding = 0 '\000', actMinSpeed = 0, 
    actMaxSpeed = 0, lastSensorBout = 0 '\000', ctrMLeftUpFlash = 0 '\000', 
    ctrMRightUpFlash = 0 '\000', folding = 0 '\000', startLeftOff = 0 '\000', 
    startRightOff = 0 '\000', halfSideShutOff = 0 '\000', 
    oldMarkerPosL = 0 '\000', oldMarkerPosR = 0 '\000', 
    timeDateActive = 0 '\000', licVtCheck = 0 '\000', trialVtCheck = 0 '\000', 
    trialAlarmActive = 0 '\000', workBeep = 0 '\000', warningBeep = 0 '\000', 
    errorBeep = 0 '\000', runLed = 0 '\000', tcLicenseOk = 0 '\000', 
    WDI_start = 0 '\000', newViewSeedCalRecRead = 0 '\000', 
    MotorStopMarkerDelay = 0}
    

    我对变量感兴趣:sensorBoutAdvance

    通过将sensorBoutAdvance周围的所有变量列出在您要读取的值之前至少8和您要读取的值之后1的范围内,并使GDB返回它们的地址:

    * calButtonL      0x2000435A
    * hssoOutput      0x2000435B
    * tramlining      0x2000435C
    * restoreCfg      0x2000435D
    * updateCfg       0x2000435E
    * boutAdvance     0x2000435F (Same address! Stop search!) 
    * boutDecrement
    * noTramlineIncDec
    * displaySfks
    * sensorBoutAdvance (Known address by &p = 0x2000435F)
    * bout
    * tramlineLeft
    * tramlineRight
    * diagOutputs
    * markerAutoDown
    * fanRpm
    * fanOffTime
    * speed
    * fsAlarmSensorNr
    * fsAlarmDisconnectedSensorNr
    

    一旦找到相同的地址,就会检测到一个位域。在这种情况下,可以在第 5 位上找到 sensorBoutAdvance。如果没有找到双地址,它可能不是 bitField,但至少位位置无关紧要。如果在您要读取的变量之后(而不是之前)找到相同的地址,则您的位位置在第一位。

    它确实需要一些解析,但对我有用,无需添加外部程序或不同的语言。

    注意:此方法仅适用于所有位域只有 1 位长的情况。

    【讨论】:

      【解决方案3】:
      import gdb
      
      class Offsets(gdb.Command):
          outfile = None
      
          def __init__(self):
              super (Offsets, self).__init__ ('offsets-of', gdb.COMMAND_DATA)
      
          def invoke(self, arg, from_tty):
              argv = gdb.string_to_argv(arg)
              if len(argv) != 2:
                  raise gdb.GdbError('offsets-of takes exactly 2 arguments.')
              self.outfile = open (argv[1], "w")
              self.traverse(gdb.lookup_type(argv[0] + '_t').fields(), argv[0], 0)
              self.outfile.close()
      
          def traverse(self, branch, fqn, address):
              for field in branch:
                  if field.type.code == gdb.TYPE_CODE_STRUCT:
                      self.traverse(field.type.fields(), fqn + '.' + field.name, address + field.bitpos//8)
                  else:
                      self.outfile.write (('fqn=' + fqn + '.%s offset=%d, size=%d\n' % (field.name, address + field.bitpos//8, field.type.sizeof)))
      
      Offsets()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-19
        • 2011-11-10
        • 1970-01-01
        • 2017-06-06
        相关资源
        最近更新 更多