2015-11-03 4 views
1

Я пытаюсь напечатать связанный список Linux в удобном для пользователя способом в Trace32.Показать связанный список Linux в Trace32

1. Есть ли какой-либо известный способ?

Если нет, то позвольте мне показать пример с modules.

У меня есть глобальная переменная

static struct list_head modules; 

где

struct list_head { 
     struct list_head *next, *prev; 
}; 

Так, в Т32 я просто увидеть список ближайших и предыдущая указатели при выполнении v.v modules, никакой полезной информации на самом деле. Однако каждый узел списка модулей является частью типа контейнера. В этом случае struct module

struct module { 
     ... 
     struct list_head list; 
     ... 
} 

Обычно, чтобы извлечь указатель контейнера Linux использует container_of макрос.

/** 
    * container_of - cast a member of a structure out to the containing structure 
    * @ptr:  the pointer to the member. 
    * @type:  the type of the container struct this is embedded in. 
    * @member:  the name of the member within the struct. 
    * 
    */ 
#define container_of(ptr, type, member) ({      \ 
     const typeof(((type *)0)->member) *__mptr = (ptr); \ 
     (type *)((char *)__mptr - offsetof(type,member));}) 

В нашем примере мы знаем, указатель на struct list_head который является list членом struct module тогда мы должны называть container_of(modules->next, struct module, list), чтобы получить указатель на контейнер.

Чтобы иметь возможность архивировать это в T32, мне нужно вычислить смещение члена list в типе контейнера.

Кто-нибудь знает, как этого достичь?

ответ

4

Ну, звучит для меня, что у вас есть два вопроса:

  1. Как отобразить связанные списки?
  2. Как получить смещение байта члена в структуре?

Для размещая связные списки Я предлагаю команду Var.CHAIN ​​или VAR.FixedCHAIN. Обе команды имеют два обязательных аргумента: переменное имя структуры и имя следующего элемента. (Вы можете посмотреть все необязательные аргументы и опции форматирования в TRACE32 manual.)

Таким образом, просматривать свой первый простой случай с

Var.CHAIN modules modules.next 

откроется окно с таблицей, не показывая вам полный список до ' next 'указывает на NULL.

Примечание: Как указано Wrymarki ниже в комментариях, эта первая часть ответа на самом деле ошибочна. Var.CHAIN ​​работает для обычных связанных списков, но не для «связанных с Linux списков». Решение для «связанных с Linux списков» (от Wrymarki) заключается в написании сценария PRACTICE, который проходит через список и добавляет записи в Var.AddWatch в окно просмотра с помощью макроса container_of() (см. Ниже).


Для получения offsset из члена в структурах я рекомендую объявить препроцессор макросы так же, как вы делаете в исходном коде. Или почти как в вашем исходном коде, так как TRACE32 не знает специфические расширения GCC типа typeof() или statement expressions.

Во всяком случае, мы можем получить макрос offsetof() с

sYmbol.NEW.MACRO offsetof(type,member) ((int)(&((type*)0)->member)) 

Препроцессора макрос может быть использован внутри каждое выражение ЯВЫ в Trace32 (со всеми Var. * Командой и функция). т.д .:

Var.AddWatch offsetof(struct module,list) 

Примечание: sYmbol.NEW.MACRO не принимает пробелы в имени макроса: Вы должны написать offsetof(type,member) вместо offsetof(type, member).

Вы можете просмотреть макросы в окне sYmbol.List.MACRO

Вы также можете получить макросы из исходного кода, если поддержка компилятора это (GCC делает с опцией -g3) при загрузке вашего ELF с параметром/MACRO: Data.LOAD.Elf * /MACRO. Но опять же: TRACE32 не понимает специфические расширения GCC или внутренние макросы, такие как «__builtin_offsetof()».


Можно также объявить container_of() препроцессора макрос с

sYmbol.NEW.MACRO container_of(ptr,type,member) ((type *)((char *)(ptr)-offsetof(type,member))) 

С его помощью можно, например, следующим образом:

Var.View container_of(modules->next,struct module,list) 
+0

Просто уточнить. Вопрос 1 заключался в том, как отображать ** связанные с Linux ** списки. 'Var.CHAIN' не выполняет эту работу в этом случае. Ответ на вопрос 2 был по существу. Большое спасибо. – wrymarkX

+0

ОК, просто узнал, что такое «Линукс связанные списки». Я уверен, что приятный просмотр списка модулей, соединенных вместе через list_head, невозможно с помощью TRACE32. Кроме того, я предполагаю, что отладчик может просматривать этот список только в том случае, если смещение «следующего» элемента внутри содержащего модуля фиксировано для всех модулей связанного списка. Предлагаю обратиться в службу поддержки Lauterbach. Возможно, они могут добавить подходящую функцию, если это возможно (они обычно делают). – Holger

+1

С помощью 'container_of()' макроса, который вы предложили, и цикла я могу сделать работу довольно хорошо. Другой аспект заключается в том, что список не заканчивается нулевым, вместо этого я вижу next = 0x55555555. Не понимаю, если это конкретная обработка Linux. – wrymarkX

0

Между командой Var.CHAIN ​​и VAR.FixedCHAIN, я думаю Var.CHAIN ​​отображается более подробную информацию, связанную список.

В случае системы ядра Linux следующая команда позволяет получить полный список связанных списков.

v.chain %m %l %tree.open %hex init_task.tasks init_task.tasks.next 

    0x0 (0)| [D:0xC1612588] (
     | [D:0xC1612588] next = 0xEE058220, 
     | [D:0xC161258C] prev = 0xE5C0B3A0), 
    0x1 (1)| [D:0xEE058220] (
     | [D:0xEE058220] next = 0xEE0587A0, 
     | [D:0xEE058224] prev = 0xC1612588), 
    0x2 (2)| [D:0xEE0587A0] (
     | [D:0xEE0587A0] next = 0xEE058D20, 
     | [D:0xEE0587A4] prev = 0xEE058220), 
    0x3 (3)| [D:0xEE058D20] (
     | [D:0xEE058D20] next = 0xEE0592A0, 
     | [D:0xEE058D24] prev = 0xEE0587A0), 
    0x4 (4)| [D:0xEE0592A0] (
     | [D:0xEE0592A0] next = 0xEE059820, 
     | [D:0xEE0592A4] prev = 0xEE058D20), 
    0x5 (5)| [D:0xEE059820] (
     | [D:0xEE059820] next = 0xEE059DA0, 
     | [D:0xEE059824] prev = 0xEE0592A0), 
    0x6 (6)| [D:0xEE059DA0] (
     | [D:0xEE059DA0] next = 0xEE05A320, 
     | [D:0xEE059DA4] prev = 0xEE059820), 
    0x7 (7)| [D:0xEE05A320] (
     | [D:0xEE05A320] next = 0xEE05A8A0, 
     | [D:0xEE05A324] prev = 0xEE059DA0), 
    0x8 (8)| [D:0xEE05A8A0] (
     | [D:0xEE05A8A0] next = 0xEE05AE20, 
     | [D:0xEE05A8A4] prev = 0xEE05A320), 
    0x9 (9)| [D:0xEE05AE20] (
     | [D:0xEE05AE20] next = 0xEE05B3A0, 
     | [D:0xEE05AE24] prev = 0xEE05A8A0), 
0x0A (10)| [D:0xEE05B3A0] (
     | [D:0xEE05B3A0] next = 0xEE05B920, 
     | [D:0xEE05B3A4] prev = 0xEE05AE20), 
0x0B (11)| [D:0xEE05B920] (
     | [D:0xEE05B920] next = 0xEE05BEA0, 
     | [D:0xEE05B924] prev = 0xEE05B3A0), 
0x0C (12)| [D:0xEE05BEA0] (
     | [D:0xEE05BEA0] next = 0xEE05C420, 
     | [D:0xEE05BEA4] prev = 0xEE05B920), 
0x0D (13)| [D:0xEE05C420] (
     | [D:0xEE05C420] next = 0xEE05DA20, 
     | [D:0xEE05C424] prev = 0xEE05BEA0), 
0x0E (14)| [D:0xEE05DA20] (
     | [D:0xEE05DA20] next = 0xEE05DFA0, 
     | [D:0xEE05DA24] prev = 0xEE05C420), 
0x0F (15)| [D:0xEE05DFA0] (
     | [D:0xEE05DFA0] next = 0xEE05E520, 
     | [D:0xEE05DFA4] prev = 0xEE05DA20),