Skip to contentSkip to conversation

scripts/gdb: make lx-dmesg command work (reliably)

PATCH Superseded André Draszik 4 participants 8 messages May 26, 2017 – May 31, 2017 GDB kernel debugging helper scripts

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 scripts/gdb: make lx-dmesg command work (reliably)

lx-dmesg needs access to the log_buf symbol from printk.c. Unfortunately, the symbol log_buf also exists in BPF's verifier.c and hence gdb can pick one or the other. If it happens to pick BPF's log_buf, lx-dmesg doesn't work:

(gdb) lx-dmesg
Python Exception <class 'gdb.MemoryError'> Cannot access memory at address 0x0:
Error occurred in Python command: Cannot access memory at address 0x0 (gdb) p log_buf
$15 = 0x0

Luckily, GDB has a way to deal with this, see
https://sourceware.org/gdb/onlinedocs/gdb/Symbols.html

(gdb) info variables ^log_buf$
All variables matching regular expression "^log_buf$":

File <linux.git>/kernel/bpf/verifier.c:
static char *log_buf;

File <linux.git>/kernel/printk/printk.c:
static char *log_buf;
(gdb) p 'verifier.c'::log_buf
$1 = 0x0
(gdb) p 'printk.c'::log_buf
$2 = 0x811a6aa0 <__log_buf> ""

By being explicit about the location of the symbol, we can make lx-dmesg work again. While at it, do the same for the other symbols we need from printk.c

---
 scripts/gdb/linux/dmesg.py | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
scripts/gdb/linux/dmesg.py +4 -4
index f9b92ece7834..11f2397d40ed 100644
@@ -23,10 +23,10 @@ class LxDmesg(gdb.Command):
         super(LxDmesg, self).__init__("lx-dmesg", gdb.COMMAND_DATA)
 
     def invoke(self, arg, from_tty):
-        log_buf_addr = int(str(gdb.parse_and_eval("log_buf")).split()[0], 16)
-        log_first_idx = int(gdb.parse_and_eval("log_first_idx"))
-        log_next_idx = int(gdb.parse_and_eval("log_next_idx"))
-        log_buf_len = int(gdb.parse_and_eval("log_buf_len"))
+        log_buf_addr = int(str(gdb.parse_and_eval("'printk.c'::log_buf")).split()[0], 16)
+        log_first_idx = int(gdb.parse_and_eval("'printk.c'::log_first_idx"))
+        log_next_idx = int(gdb.parse_and_eval("'printk.c'::log_next_idx"))
+        log_buf_len = int(gdb.parse_and_eval("'printk.c'::log_buf_len"))
 
         inf = gdb.inferiors()[0]
         start = log_buf_addr + log_first_idx
Signature · 1 line
2.11.0
maintainer
#1 lore raw
Quoted 41 lines · André Draszik

lx-dmesg needs access to the log_buf symbol from printk.c. Unfortunately, the symbol log_buf also exists in BPF's verifier.c and hence gdb can pick one or the other. If it happens to pick BPF's log_buf, lx-dmesg doesn't work:

(gdb) lx-dmesg
Python Exception <class 'gdb.MemoryError'> Cannot access memory at address 0x0:
Error occurred in Python command: Cannot access memory at address 0x0 (gdb) p log_buf
$15 = 0x0

Luckily, GDB has a way to deal with this, see
https://sourceware.org/gdb/onlinedocs/gdb/Symbols.html

(gdb) info variables ^log_buf$
All variables matching regular expression "^log_buf$":

File <linux.git>/kernel/bpf/verifier.c:
static char *log_buf;

File <linux.git>/kernel/printk/printk.c:
static char *log_buf;
(gdb) p 'verifier.c'::log_buf
$1 = 0x0
(gdb) p 'printk.c'::log_buf
$2 = 0x811a6aa0 <__log_buf> ""

By being explicit about the location of the symbol, we can make lx-dmesg work again. While at it, do the same for the other symbols we need from printk.c

---
 scripts/gdb/linux/dmesg.py | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
scripts/gdb/linux/dmesg.py +0 -0
index f9b92ece7834..11f2397d40ed 100644

scripts/gdb/linux/dmesg.py class LxDmesg(gdb.Command): · line 26

Quoted 8 lines
scripts/gdb/linux/dmesg.py +1 -4
@@ -23,10 +23,10 @@ class LxDmesg(gdb.Command):
         super(LxDmesg, self).__init__("lx-dmesg", gdb.COMMAND_DATA)
 
     def invoke(self, arg, from_tty):
-        log_buf_addr = int(str(gdb.parse_and_eval("log_buf")).split()[0], 16)
-        log_first_idx = int(gdb.parse_and_eval("log_first_idx"))
-        log_next_idx = int(gdb.parse_and_eval("log_next_idx"))
-        log_buf_len = int(gdb.parse_and_eval("log_buf_len"))
+        log_buf_addr = int(str(gdb.parse_and_eval("'printk.c'::log_buf")).split()[0], 16)

Overlong line. Please stay pep8 compliant.

scripts/gdb/linux/dmesg.py class LxDmesg(gdb.Command): · line 32

Quoted 7 lines
scripts/gdb/linux/dmesg.py +3 -0
+        log_first_idx = int(gdb.parse_and_eval("'printk.c'::log_first_idx"))
+        log_next_idx = int(gdb.parse_and_eval("'printk.c'::log_next_idx"))
+        log_buf_len = int(gdb.parse_and_eval("'printk.c'::log_buf_len"))
 
         inf = gdb.inferiors()[0]
         start = log_buf_addr + log_first_idx

Looks good otherwise, thanks for addressing this!

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT RDA ITP SES-DE
Corporate Competence Center Embedded Linux
#2 lore raw
Quoted 5 lines · Jan Kiszka
Quoted 1 line · André Draszik

+ log_buf_addr = int(str(gdb.parse_and_eval("'printk.c'::log_buf")).split()[0], 16)

Overlong line. Please stay pep8 compliant.

What I heard from colleague of mine couple of years ago, they (their team) moved to 100 characters in Python scripts because of somehow stupid recommendations from last century.

Signature · 2 lines
With Best Regards,
Andy Shevchenko
maintainer
#3 lore raw
Quoted 10 lines · Andy Shevchenko
Quoted 5 lines · Jan Kiszka
Quoted 1 line · André Draszik

+ log_buf_addr = int(str(gdb.parse_and_eval("'printk.c'::log_buf")).split()[0], 16)

Overlong line. Please stay pep8 compliant.

What I heard from colleague of mine couple of years ago, they (their team) moved to 100 characters in Python scripts because of somehow stupid recommendations from last century.

Well, it happens to be in line with the kernel preference for C code. We can discuss a different style when the kernel relaxes its own. ;)

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT RDA ITP SES-DE
Corporate Competence Center Embedded Linux
#4 lore raw

PATCH v2 1/1 scripts/gdb: make lx-dmesg command work (reliably)

In reply to André Draszik

lx-dmesg needs access to the log_buf symbol from printk.c. Unfortunately, the symbol log_buf also exists in BPF's verifier.c and hence gdb can pick one or the other. If it happens to pick BPF's log_buf, lx-dmesg doesn't work:

(gdb) lx-dmesg
Python Exception <class 'gdb.MemoryError'> Cannot access memory at address 0x0:
Error occurred in Python command: Cannot access memory at address 0x0 (gdb) p log_buf
$15 = 0x0

Luckily, GDB has a way to deal with this, see
https://sourceware.org/gdb/onlinedocs/gdb/Symbols.html

(gdb) info variables ^log_buf$
All variables matching regular expression "^log_buf$":

File <linux.git>/kernel/bpf/verifier.c:
static char *log_buf;

File <linux.git>/kernel/printk/printk.c:
static char *log_buf;
(gdb) p 'verifier.c'::log_buf
$1 = 0x0
(gdb) p 'printk.c'::log_buf
$2 = 0x811a6aa0 <__log_buf> ""
(gdb) p &log_buf
$3 = (char **) 0x8120fe40 <log_buf>
(gdb) p &'verifier.c'::log_buf
$4 = (char **) 0x8120fe40 <log_buf>
(gdb) p &'printk.c'::log_buf
$5 = (char **) 0x8048b7d0 <log_buf>

By being explicit about the location of the symbol, we can make lx-dmesg work again. While at it, do the same for the other symbols we need from printk.c

---
v2: Commit message slightly updated

---
 scripts/gdb/linux/dmesg.py | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
scripts/gdb/linux/dmesg.py +4 -4
index f9b92ece7834..11f2397d40ed 100644
@@ -23,10 +23,10 @@ class LxDmesg(gdb.Command):
         super(LxDmesg, self).__init__("lx-dmesg", gdb.COMMAND_DATA)
 
     def invoke(self, arg, from_tty):
-        log_buf_addr = int(str(gdb.parse_and_eval("log_buf")).split()[0], 16)
-        log_first_idx = int(gdb.parse_and_eval("log_first_idx"))
-        log_next_idx = int(gdb.parse_and_eval("log_next_idx"))
-        log_buf_len = int(gdb.parse_and_eval("log_buf_len"))
+        log_buf_addr = int(str(gdb.parse_and_eval("'printk.c'::log_buf")).split()[0], 16)
+        log_first_idx = int(gdb.parse_and_eval("'printk.c'::log_first_idx"))
+        log_next_idx = int(gdb.parse_and_eval("'printk.c'::log_next_idx"))
+        log_buf_len = int(gdb.parse_and_eval("'printk.c'::log_buf_len"))
 
         inf = gdb.inferiors()[0]
         start = log_buf_addr + log_first_idx
Signature · 1 line
2.11.0
#5 lore raw

PATCH v3 1/1 scripts/gdb: make lx-dmesg command work (reliably)

In reply to André Draszik

lx-dmesg needs access to the log_buf symbol from printk.c. Unfortunately, the symbol log_buf also exists in BPF's verifier.c and hence gdb can pick one or the other. If it happens to pick BPF's log_buf, lx-dmesg doesn't work:

(gdb) lx-dmesg
Python Exception <class 'gdb.MemoryError'> Cannot access memory at address 0x0:
Error occurred in Python command: Cannot access memory at address 0x0 (gdb) p log_buf
$15 = 0x0

Luckily, GDB has a way to deal with this, see
https://sourceware.org/gdb/onlinedocs/gdb/Symbols.html

(gdb) info variables ^log_buf$
All variables matching regular expression "^log_buf$":

File <linux.git>/kernel/bpf/verifier.c:
static char *log_buf;

File <linux.git>/kernel/printk/printk.c:
static char *log_buf;
(gdb) p 'verifier.c'::log_buf
$1 = 0x0
(gdb) p 'printk.c'::log_buf
$2 = 0x811a6aa0 <__log_buf> ""
(gdb) p &log_buf
$3 = (char **) 0x8120fe40 <log_buf>
(gdb) p &'verifier.c'::log_buf
$4 = (char **) 0x8120fe40 <log_buf>
(gdb) p &'printk.c'::log_buf
$5 = (char **) 0x8048b7d0 <log_buf>

By being explicit about the location of the symbol, we can make lx-dmesg work again. While at it, do the same for the other symbols we need from printk.c

---
v3: pep8 compliant
v2: Commit message slightly updated

---
 scripts/gdb/linux/dmesg.py | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)
scripts/gdb/linux/dmesg.py +5 -4
index f9b92ece7834..5afd1098e33a 100644
@@ -23,10 +23,11 @@ class LxDmesg(gdb.Command):
         super(LxDmesg, self).__init__("lx-dmesg", gdb.COMMAND_DATA)
 
     def invoke(self, arg, from_tty):
-        log_buf_addr = int(str(gdb.parse_and_eval("log_buf")).split()[0], 16)
-        log_first_idx = int(gdb.parse_and_eval("log_first_idx"))
-        log_next_idx = int(gdb.parse_and_eval("log_next_idx"))
-        log_buf_len = int(gdb.parse_and_eval("log_buf_len"))
+        log_buf_addr = int(str(gdb.parse_and_eval(
+            "'printk.c'::log_buf")).split()[0], 16)
+        log_first_idx = int(gdb.parse_and_eval("'printk.c'::log_first_idx"))
+        log_next_idx = int(gdb.parse_and_eval("'printk.c'::log_next_idx"))
+        log_buf_len = int(gdb.parse_and_eval("'printk.c'::log_buf_len"))
 
         inf = gdb.inferiors()[0]
         start = log_buf_addr + log_first_idx
Signature · 1 line
2.11.0
maintainer Acked-by on v3 1/1
#6 lore raw
Quoted 57 lines · André Draszik

lx-dmesg needs access to the log_buf symbol from printk.c. Unfortunately, the symbol log_buf also exists in BPF's verifier.c and hence gdb can pick one or the other. If it happens to pick BPF's log_buf, lx-dmesg doesn't work:

(gdb) lx-dmesg
Python Exception <class 'gdb.MemoryError'> Cannot access memory at address 0x0:
Error occurred in Python command: Cannot access memory at address 0x0 (gdb) p log_buf
$15 = 0x0

Luckily, GDB has a way to deal with this, see
https://sourceware.org/gdb/onlinedocs/gdb/Symbols.html

(gdb) info variables ^log_buf$
All variables matching regular expression "^log_buf$":

File <linux.git>/kernel/bpf/verifier.c:
static char *log_buf;

File <linux.git>/kernel/printk/printk.c:
static char *log_buf;
(gdb) p 'verifier.c'::log_buf
$1 = 0x0
(gdb) p 'printk.c'::log_buf
$2 = 0x811a6aa0 <__log_buf> ""
(gdb) p &log_buf
$3 = (char **) 0x8120fe40 <log_buf>
(gdb) p &'verifier.c'::log_buf
$4 = (char **) 0x8120fe40 <log_buf>
(gdb) p &'printk.c'::log_buf
$5 = (char **) 0x8048b7d0 <log_buf>

By being explicit about the location of the symbol, we can make lx-dmesg work again. While at it, do the same for the other symbols we need from printk.c

---
v3: pep8 compliant
v2: Commit message slightly updated

---
 scripts/gdb/linux/dmesg.py | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)
scripts/gdb/linux/dmesg.py +0 -2
index f9b92ece7834..5afd1098e33a 100644
@@ -23,10 +23,11 @@ class LxDmesg(gdb.Command):
         super(LxDmesg, self).__init__("lx-dmesg", gdb.COMMAND_DATA)
 
     def invoke(self, arg, from_tty):
-        log_buf_addr = int(str(gdb.parse_and_eval("log_buf")).split()[0], 16)
-        log_first_idx = int(gdb.parse_and_eval("log_first_idx"))

scripts/gdb/linux/dmesg.py class LxDmesg(gdb.Command): · line 33

Quoted 10 lines
scripts/gdb/linux/dmesg.py +5 -2
-        log_next_idx = int(gdb.parse_and_eval("log_next_idx"))
-        log_buf_len = int(gdb.parse_and_eval("log_buf_len"))
+        log_buf_addr = int(str(gdb.parse_and_eval(
+            "'printk.c'::log_buf")).split()[0], 16)
+        log_first_idx = int(gdb.parse_and_eval("'printk.c'::log_first_idx"))
+        log_next_idx = int(gdb.parse_and_eval("'printk.c'::log_next_idx"))
+        log_buf_len = int(gdb.parse_and_eval("'printk.c'::log_buf_len"))
 
         inf = gdb.inferiors()[0]
         start = log_buf_addr + log_first_idx

Andrew, please include in your queue.

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT RDA ITP SES-DE
Corporate Competence Center Embedded Linux
Tested-by
#7 lore raw

Hi André, Jan, Andrew,

Quoted 34 lines · Jan Kiszka
Quoted 33 lines · André Draszik

lx-dmesg needs access to the log_buf symbol from printk.c. Unfortunately, the symbol log_buf also exists in BPF's verifier.c and hence gdb can pick one or the other. If it happens to pick BPF's log_buf, lx-dmesg doesn't work:

(gdb) lx-dmesg
Python Exception <class 'gdb.MemoryError'> Cannot access memory at address 0x0:
Error occurred in Python command: Cannot access memory at address 0x0 (gdb) p log_buf
$15 = 0x0

Luckily, GDB has a way to deal with this, see
https://sourceware.org/gdb/onlinedocs/gdb/Symbols.html

(gdb) info variables ^log_buf$
All variables matching regular expression "^log_buf$":

File <linux.git>/kernel/bpf/verifier.c:
static char *log_buf;

File <linux.git>/kernel/printk/printk.c:
static char *log_buf;
(gdb) p 'verifier.c'::log_buf
$1 = 0x0
(gdb) p 'printk.c'::log_buf
$2 = 0x811a6aa0 <__log_buf> ""
(gdb) p &log_buf
$3 = (char **) 0x8120fe40 <log_buf>
(gdb) p &'verifier.c'::log_buf
$4 = (char **) 0x8120fe40 <log_buf>
(gdb) p &'printk.c'::log_buf
$5 = (char **) 0x8048b7d0 <log_buf>

Quoted 5 lines
Quoted 5 lines

By being explicit about the location of the symbol, we can make lx-dmesg work again. While at it, do the same for the other symbols we need from printk.c

Nice to see you again André :D

Quoted 25 lines
Quoted 25 lines

---
v3: pep8 compliant
v2: Commit message slightly updated

---
 scripts/gdb/linux/dmesg.py | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)
scripts/gdb/linux/dmesg.py +5 -4
index f9b92ece7834..5afd1098e33a 100644
@@ -23,10 +23,11 @@ class LxDmesg(gdb.Command):
         super(LxDmesg, self).__init__("lx-dmesg", gdb.COMMAND_DATA)
 
     def invoke(self, arg, from_tty):
-        log_buf_addr = int(str(gdb.parse_and_eval("log_buf")).split()[0], 16)
-        log_first_idx = int(gdb.parse_and_eval("log_first_idx"))
-        log_next_idx = int(gdb.parse_and_eval("log_next_idx"))
-        log_buf_len = int(gdb.parse_and_eval("log_buf_len"))
+        log_buf_addr = int(str(gdb.parse_and_eval(
+            "'printk.c'::log_buf")).split()[0], 16)
+        log_first_idx = int(gdb.parse_and_eval("'printk.c'::log_first_idx"))
+        log_next_idx = int(gdb.parse_and_eval("'printk.c'::log_next_idx"))
+        log_buf_len = int(gdb.parse_and_eval("'printk.c'::log_buf_len"))
 
Quoted 5 lines

scripts/gdb/linux/dmesg.py class LxDmesg(gdb.Command): · line 33

Quoted 3 lines
scripts/gdb/linux/dmesg.py +0 -0
         inf = gdb.inferiors()[0]
         start = log_buf_addr + log_first_idx

Sorry for the delay - I'm in Tokyo for Linux OSS Japan.

This looks good to me and I've verified it locally.

Quoted 5 lines

Andrew, please include in your queue.

Jan

Signature · 3 lines
Regards

Kieran Bingham