我尝试使用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是否能够提供某种输出来解决这个问题?
答案 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()