mirror of
https://github.com/JakeHillion/drgn.git
synced 2024-12-22 17:23:06 +00:00
libdrgn: add THREAD_SIZE to Linux kernel object finder
Despite the naming, this is the kernel stack size.
This commit is contained in:
parent
971a2d3687
commit
4d8597f0f8
@ -234,6 +234,33 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct drgn_error *
|
||||
linux_kernel_get_thread_size(struct drgn_program *prog, uint64_t *ret)
|
||||
{
|
||||
struct drgn_error *err;
|
||||
struct drgn_qualified_type thread_union_type;
|
||||
struct drgn_member_info stack_member;
|
||||
|
||||
if (!prog->thread_size) {
|
||||
err = drgn_program_find_type(prog, "union thread_union", NULL,
|
||||
&thread_union_type);
|
||||
if (err)
|
||||
return err;
|
||||
err = drgn_program_member_info(prog, thread_union_type.type,
|
||||
"stack", &stack_member);
|
||||
if (err)
|
||||
return err;
|
||||
err = drgn_type_sizeof(stack_member.qualified_type.type,
|
||||
&prog->thread_size);
|
||||
if (err) {
|
||||
prog->thread_size = 0;
|
||||
return err;
|
||||
}
|
||||
}
|
||||
*ret = prog->thread_size;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct drgn_error *linux_kernel_object_find(const char *name, size_t name_len,
|
||||
const char *filename,
|
||||
enum drgn_find_object_flags flags,
|
||||
@ -296,6 +323,20 @@ struct drgn_error *linux_kernel_object_find(const char *name, size_t name_len,
|
||||
return drgn_object_set_unsigned(ret, qualified_type,
|
||||
~(prog->vmcoreinfo.page_size - 1),
|
||||
0);
|
||||
} else if (name_len == strlen("THREAD_SIZE") &&
|
||||
memcmp(name, "THREAD_SIZE", name_len) == 0) {
|
||||
uint64_t thread_size;
|
||||
|
||||
err = linux_kernel_get_thread_size(prog, &thread_size);
|
||||
if (err)
|
||||
return err;
|
||||
err = drgn_type_index_find_primitive(&prog->tindex,
|
||||
DRGN_C_TYPE_UNSIGNED_LONG,
|
||||
&qualified_type.type);
|
||||
if (err)
|
||||
return err;
|
||||
return drgn_object_set_unsigned(ret, qualified_type,
|
||||
thread_size, 0);
|
||||
} else if (name_len == strlen("UTS_RELEASE") &&
|
||||
memcmp(name, "UTS_RELEASE", name_len) == 0) {
|
||||
size_t len;
|
||||
|
@ -74,6 +74,8 @@ struct drgn_program {
|
||||
uint64_t page_offset;
|
||||
/* Cached vmemmap. */
|
||||
uint64_t vmemmap;
|
||||
/* Cached THREAD_SIZE. */
|
||||
uint64_t thread_size;
|
||||
#ifdef WITH_LIBKDUMPFILE
|
||||
kdump_ctx_t *kdump_ctx;
|
||||
#endif
|
||||
|
@ -15,6 +15,10 @@ from tests.helpers.linux import (
|
||||
)
|
||||
|
||||
|
||||
def is_power_of_two(n):
|
||||
return n != 0 and (n & (n - 1)) == 0
|
||||
|
||||
|
||||
class TestSched(LinuxHelperTestCase):
|
||||
def test_task_state_to_char(self):
|
||||
task = find_task(self.prog, os.getpid())
|
||||
@ -35,3 +39,15 @@ class TestSched(LinuxHelperTestCase):
|
||||
self.assertEqual(task_state_to_char(task), "Z")
|
||||
|
||||
os.waitpid(pid, 0)
|
||||
|
||||
def test_thread_size(self):
|
||||
# As far as I can tell, there's no way to query this value from
|
||||
# userspace, so at least sanity check that it's a power-of-two multiple
|
||||
# of the page size and that we can read the entire stack.
|
||||
thread_size = self.prog["THREAD_SIZE"].value_()
|
||||
page_size = self.prog["PAGE_SIZE"].value_()
|
||||
self.assertEqual(thread_size % page_size, 0)
|
||||
self.assertTrue(is_power_of_two(thread_size // page_size))
|
||||
|
||||
task = find_task(self.prog, os.getpid())
|
||||
self.prog.read(task.stack, thread_size)
|
||||
|
Loading…
Reference in New Issue
Block a user