2015-08-31 84 views
2

我試圖在GDB中使用ARM .elf輸出來確定地址值和大小。 與通常的p &和打印函數我可以確定大部分地址和變量大小,但我無法弄清楚該變量是否是一個bitValue。GDB位位值

舉個例子:

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」它將返回相同的地址(因爲它使用相同的地址),但沒有給我這個位的位置。我也不知道它是否真的是一個bit值,或者只是一個布爾值,取一個uint8_t的空格。

爲了闡明我需要做的事情:給GDB一個名字,什麼可能是一個bitValue,然後返回給我正確的地址和類型。如果這個類型是一個bitValue,我需要找到位的位置。對於非bitValues這工作正常,bitValues現在造成麻煩。

GDB能夠給出某種輸出來解決這個問題嗎?

+0

實際的底層類型取決於'bool_t',它是什麼?不,沒有辦法獲得位的位置。哦,如果每一位都是「uint8_t」,那麼每一位肯定會有自己的地址,不會像現在這樣分享。 –

+0

bool_t是一個無符號字符。而且,是的,這很明顯,重點是我只需要使用1個變量就可以知道它,而不是全部使用它們並檢查雙打。 – koldewb

+0

C語言規範保證在位域中設置位設置那一點。編譯器如何實現它並不重要,但我認爲使用更大類型的實際位很常見(並且考慮到兩位使用相同的地址,似乎是您的編譯器實現,因爲它們是一個位較大型)。並回答你的問題,你想要的是不可能的,沒有支持它。你可以相信,如果你在比特場中有一點點,它將被正確處理。 –

回答

0

我已經自己解決了這個問題。 因爲我不知道如何,並且似乎沒有直接返回位位置的方法,所以可以通過詢問GDB的多個地址來計算它。

使用p &命令可以確定變量的地址,但不能確定其位字段或位字段的位置。 通過使用一個結構GDB的打印命令時,bitValue我需要的位置,它將在這個結構返回所有可用的值,例如:

我找位域: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

通過你想讀和1你想閱讀背後的價值,並讓GDB返回它們的地址值之前上市的一系列至少8內圍繞sensorBoutAdvance所有的變量:

* 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。在這種情況下,可以在位5上找到sensorBoutAdvance。如果沒有找到雙地址,它可能不是一個bitField,但至少該位的位置並不重要。如果在要讀取的變量之後(而不是之前)找到相同的地址,則位位置位於第一位。

它肯定需要一些解析,但爲我工作,而無需添加外部程序或不同的語言。

注意:此方法只適用於所有位域只有1位長的情況。

0

無法直接使用gdb表達式API獲取此信息。這沒什麼真正深刻的原因 - 當然gdb知道位的位置 - 但這是gdb表達式模仿被調試的語言的事實的結果,以及沒有人曾經打擾過要暴露它。由於我以前從來沒有聽說過任何人想要這個,所以我認爲可以肯定地說這是一個罕見的要求。

該信息可通過gdb的Python API獲取。特別是,如果遍歷某個類型的字段,則Field對象將具有一個bitpos成員,該成員具有數據的位偏移量。請注意,偏移量來自封閉的struct的開頭。

在Python中編寫一個打印此信息的新命令將是一件相對簡單的事情。