GDB位位置位值

时间:2015-08-31 06:44:28

标签: c gdb arm elf

我尝试使用GDB中的ARM .elf输出来确定地址值和大小。 通常的p&和打印功能我可以确定大多数地址和可变大小,但我无法确定变量是否为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,我需要找到位位置。对于非bitValues,这可以正常工作,bitValues现在会造成麻烦。

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

3 个答案:

答案 0 :(得分:1)

无法使用gdb表达式API直接获取此信息。没有真正深层次的理由 - 当然gdb知道位位置 - 但这是gdb表达式模仿被调试语言这一事实​​的结果,加上没有人会费心去暴露它。由于我以前从未听说过有人想过这个,我认为这是一个罕见的请求是安全的。

这些信息可以通过gdb的Python API获得。特别是,如果迭代一个类型的字段,Field对象将具有一个bitpos成员,该成员具有数据的位偏移量。请注意,偏移量来自封闭struct的开头。

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

答案 1 :(得分:0)

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

使用p&命令可以确定变量的地址,但不能确定它的bitField或它的位位置。 通过在结构上使用GDB的print命令,我需要的bitValue的位置,它将返回此结构中的所有可用值,例如:

我正在寻找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

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

肯定需要一些解析,但对我来说无需添加外部程序或不同的语言。

注意:此方法仅在所有位字段仅为1位长时才有效。

答案 2 :(得分:-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()