GDB 位位置位值

GDB bit position bit-values

我正在尝试使用 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" 的地址时,它将 return 相同的地址(因为它使用相同的地址),但不给我位位置。我也不知道它是否真的是一个位值或只是一个取 uint8_t.

的 space 的布尔值

为了阐明我需要做什么:只给 GDB 一个名字,可能是一个 bitValue,return 给我正确的地址和类型。如果这个类型是一个 bitValue,我需要找到位的位置。对于非 bitValues 这工作正常,bitValues 现在造成了麻烦。

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

无法直接使用 gdb 表达式 API 获取此信息。这并没有真正深刻的原因——当然 gdb 知道位的位置——但这是 gdb 表达式模仿正在调试的语言这一事实​​的结果,再加上没有人愿意公开它。由于我以前从未听说过有人想要这个,我认为可以肯定地说这是一个罕见的请求。

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

开始的

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

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

使用p&命令可以确定变量的地址,但不能确定它的位域或它的位位置。 通过在结构上使用 GDB 的打印命令,我需要的 bitValue 的位置,它将 return 这个结构中的所有可用值,示例:

我正在寻找位域:MachineToUi.tramlining.sensorBoutAdvance

MachineToUi 将 return 以下内容:

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

我对变量感兴趣:sensorBoutAdvance

通过列出sensorBoutAdvance周围的所有变量,范围在你要读取的值前至少8个和你要读取的值后1个,并使GDB return它们的地址:

* 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。如果没有找到双地址,则它可能不是位字段,但至少位位置无关紧要。如果在您要读取的变量之后(而不是之前)找到相同的地址,则您的位位置在第一位。

它确实需要一些解析,但对我来说不需要添加外部程序或不同的语言就可以使用。

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

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()