-
Notifications
You must be signed in to change notification settings - Fork 19
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
dm: add dmsetup table support for linear target #56
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,11 +7,13 @@ | |
from typing import Iterable | ||
from typing import Tuple | ||
|
||
from drgn import cast | ||
from drgn import Object | ||
from drgn import Program | ||
from drgn.helpers.linux.list import list_for_each_entry | ||
from drgn.helpers.linux.rbtree import rbtree_inorder_for_each_entry | ||
|
||
from drgn_tools.block import blkdev_name | ||
from drgn_tools.corelens import CorelensModule | ||
from drgn_tools.module import ensure_debuginfo | ||
from drgn_tools.table import print_table | ||
|
@@ -104,6 +106,70 @@ def show_dm(prog: Program) -> None: | |
print_table(output) | ||
|
||
|
||
def dm_table(dm: Object) -> Object: | ||
""" | ||
return the ``struct dm_table *`` | ||
|
||
There were two definitions of ``struct dm_table`` before commit | ||
1d3aa6f683b1("dm: remove dummy definition of 'struct dm_table'") | ||
which was included in v4.10, specify file for the correct symbol. | ||
""" | ||
if kernel_version(dm.prog_) < (4, 10, 0): | ||
table_type = dm.prog_.type( | ||
"struct dm_table *", "drivers/md/dm-table.c" | ||
) | ||
Comment on lines
+118
to
+120
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oof. This is quite frustrating, especially because CTF has no way to represent the filename where a type is declared. It resolves name collisions in its own way, which has to do with kernel module names, but it's not perfect either. Unfortunately there's not much to do about this in the context of this PR. It's merely another concern for me to keep in mind for CTF. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Interestingly enough, I took a look at the UEK4 CTF archives, and found that the "undefined" variant of dm_table is not even included in the CTF archive, since it never gets used by anything. I guess CTF is "smart enough" to handle this situation. Also, UEK4 is not currently planned to be supported for CTF, so that's not much of an issue anyway. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CTF is awesome! |
||
return cast(table_type, dm.map) | ||
else: | ||
return cast("struct dm_table *", dm.map) | ||
|
||
|
||
def dm_target_name(dm: Object) -> str: | ||
table = dm_table(dm) | ||
if table.value_() == 0x0: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again, another note that for NULL testing, you can simply do |
||
return "None" | ||
return table.targets.type.name.string_().decode() | ||
|
||
|
||
def show_table_linear(dm: Object, name: str) -> None: | ||
table = dm_table(dm) | ||
for tid in range(table.num_targets): | ||
target = table.targets[tid] | ||
dev = cast("struct linear_c *", target.private) | ||
print( | ||
"%s: %d %d linear %d:%d [%s] %d" | ||
% ( | ||
name, | ||
int(target.begin), | ||
int(target.len), | ||
dev.dev.bdev.bd_dev >> 20, | ||
dev.dev.bdev.bd_dev & 0xFFFFF, | ||
blkdev_name(dev.dev.bdev), | ||
dev.start, | ||
) | ||
) | ||
|
||
|
||
dmtable_handler = { | ||
"linear": show_table_linear, | ||
} | ||
|
||
|
||
def show_dm_table(prog: Program) -> None: | ||
for dm, name in for_each_dm(prog): | ||
target_name = dm_target_name(dm) | ||
if target_name == "None": | ||
print("dm %s doesn't have a target" % hex(dm.value_())) | ||
continue | ||
elif target_name not in dmtable_handler.keys(): | ||
print( | ||
"dm %s used non-support target %s" | ||
% (hex(dm.value_()), target_name) | ||
) | ||
continue | ||
else: | ||
dmtable_handler[target_name](dm, name) | ||
|
||
|
||
class Dm(CorelensModule): | ||
"""Display info about device mapper devices""" | ||
|
||
|
@@ -112,3 +178,4 @@ class Dm(CorelensModule): | |
|
||
def run(self, prog: Program, args: argparse.Namespace) -> None: | ||
show_dm(prog) | ||
show_dm_table(prog) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Python has a neat feature where you can index with a negative integer, and it will instead index backwards from the end of whatever you're indexing. This means you can omit
len(disk_name)
here, it's quite nice:Anyway, this is just a note for the future :) Not something to block the PR on!