Skip to content

Helper to dump ftrace buffer #162

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

richl9
Copy link
Contributor

@richl9 richl9 commented May 19, 2025

No description provided.

@oracle-contributor-agreement oracle-contributor-agreement bot added the OCA Verified All contributors have signed the Oracle Contributor Agreement. label May 19, 2025
@richl9
Copy link
Contributor Author

richl9 commented May 19, 2025

wip: fixing some .dat formatting issue

@richl9 richl9 force-pushed the richard/ftrace branch 2 times, most recently from 1918fa0 to 7c6b874 Compare May 19, 2025 18:36
@richl9 richl9 force-pushed the richard/ftrace branch 4 times, most recently from 8d4d837 to 86f44f9 Compare May 19, 2025 21:30
Orabug: 37944905
Signed-off-by: Richard Li <[email protected]>
Copy link
Member

@brenns10 brenns10 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A question to go along with these suggestions: how would I test this? Or how have you tested? It looks useful -- can the data simply be used with trace-cmd?


from drgn_tools.corelens import CorelensModule

PAGE_SIZE = 4096
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer you not store this as a constant. It's totally fine to load it once at the beginning of a function. Believe it or not, it's quite efficient to get this from the Program. PAGE_SIZE is implemented as a special-case, which means that drgn doesn't need to do any work to determine its value.

https://github.com/osandov/drgn/blob/main/libdrgn/linux_kernel_object_find.inc.strswitch#L13-L16

https://github.com/osandov/drgn/blob/main/libdrgn/linux_kernel.c#L170-L182

Comment on lines +32 to +35
count = 0
while True:
if count >= cpu_buffer.nr_pages:
break
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this be simpler as:

for count in range(1, cpu_buffer.nr_pages):
    ....

Comment on lines +62 to +63
if reader_page_addr:
linear_pages.append(reader_page_addr)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reading the ring buffer source code, I'm not sure I understand this. The reader_page is fully removed from the ring buffer. If the ring buffer has overwritten, then the reader page may not be contiguous with any of the data in the ring buffer. Is it a good idea to include its data here?

Actually, I admit I'm not fully understanding this code, even as I've spent some time with kernel/trace/ring_buffer.c! I think some comments would be useful, and maybe you could walk me through it on zoom.

magic = b"Dtracing6\0\0\0"
magic_tag = 0x17 if is_little_endian else 0x18
f.write(magic_tag.to_bytes(1, "little"))
f.write(0x08.to_bytes(1, "little"))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0x08.to_bytes(1, "little")) could be replaced by the simpler b'\x08' literal. And the same could be done with the magic_tag above.

Comment on lines +175 to +189
f.write(
(0).to_bytes(4, "little" if is_little_endian else "big")
) # event format
f.write(
(0).to_bytes(4, "little" if is_little_endian else "big")
) # event systems
f.write(
(0).to_bytes(4, "little" if is_little_endian else "big")
) # kallsyms
f.write(
(0).to_bytes(4, "little" if is_little_endian else "big")
) # ftrace_printk
f.write(
(0).to_bytes(8, "little" if is_little_endian else "big")
) # cmdlines
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might want to consider using the struct module for much of this. It's designed exactly for converting basic data types into a packed binary encoding, and it's a lot more concise then doing the .to_bytes() thing (which, admittedly, I did not know about, so thanks for teaching me that!).

You could replace this, for example, with:

Suggested change
f.write(
(0).to_bytes(4, "little" if is_little_endian else "big")
) # event format
f.write(
(0).to_bytes(4, "little" if is_little_endian else "big")
) # event systems
f.write(
(0).to_bytes(4, "little" if is_little_endian else "big")
) # kallsyms
f.write(
(0).to_bytes(4, "little" if is_little_endian else "big")
) # ftrace_printk
f.write(
(0).to_bytes(8, "little" if is_little_endian else "big")
) # cmdlines
endian = '<' if is_little_endian else '>'
f.write(struct.pack(f'{endian}LLLLQ', 0, 0, 0, 0, 0))

There are also tools for placing nul-padded constant width strings in (e.g. "flyrecord" below). I think with struct this whole function will get a lot simpler!

@richl9
Copy link
Contributor Author

richl9 commented Jun 13, 2025

Hi @brenns10 , thanks for the comment. This is still wip. It will role out soon:)

@brenns10 brenns10 marked this pull request as draft June 16, 2025 18:32
@brenns10
Copy link
Member

Got it, I've marked it as a draft, you can change it back once you're ready for review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
OCA Verified All contributors have signed the Oracle Contributor Agreement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants