@@ -386,8 +386,21 @@ fn extract_tpbase_offset_from_btf() -> Result<u64> {
386386
387387 #[ cfg( target_arch = "aarch64" ) ]
388388 {
389- // For ARM64: task_struct.thread.uw.tp_value
390- // Default offset for common kernel configurations
389+ // Try parsing /sys/kernel/btf/vmlinux for ARM64
390+ match parse_btf_for_tpbase ( ) {
391+ Ok ( offset) => {
392+ debug ! (
393+ "Extracted TPBASE offset {} ({:#x}) from BTF" ,
394+ offset, offset
395+ ) ;
396+ return Ok ( offset) ;
397+ }
398+ Err ( e) => {
399+ debug ! ( "BTF parsing failed: {}" , e) ;
400+ }
401+ }
402+
403+ // Fallback to hardcoded defaults based on common kernel configurations
391404 get_default_tpbase_offset ( )
392405 }
393406
@@ -400,7 +413,7 @@ fn extract_tpbase_offset_from_btf() -> Result<u64> {
400413}
401414
402415/// Parse BTF information from /sys/kernel/btf/vmlinux to get TPBASE offset
403- #[ cfg( target_arch = "x86_64" ) ]
416+ #[ cfg( any ( target_arch = "x86_64" , target_arch = "aarch64" ) ) ]
404417fn parse_btf_for_tpbase ( ) -> Result < u64 > {
405418 use std:: fs:: File ;
406419 use std:: io:: Read ;
@@ -419,8 +432,11 @@ fn parse_btf_for_tpbase() -> Result<u64> {
419432 parse_btf_task_struct_fsbase ( & btf_data)
420433}
421434
422- /// Parse BTF data to find task_struct.thread.fsbase offset
423- #[ cfg( target_arch = "x86_64" ) ]
435+ /// Parse BTF task_struct to find fsbase/tp_value offset
436+ ///
437+ /// On x86_64: finds task_struct.thread.fsbase
438+ /// On ARM64: finds task_struct.thread.uw.tp_value
439+ #[ cfg( any( target_arch = "x86_64" , target_arch = "aarch64" ) ) ]
424440fn parse_btf_task_struct_fsbase ( btf_data : & [ u8 ] ) -> Result < u64 > {
425441 // BTF header structure (from include/uapi/linux/btf.h)
426442 // struct btf_header {
@@ -469,13 +485,34 @@ fn parse_btf_task_struct_fsbase(btf_data: &[u8]) -> Result<u64> {
469485 let task_struct_id = find_btf_struct_by_name ( type_section, str_section, "task_struct" ) ?;
470486
471487 // Find thread member in task_struct
472- let thread_offset =
473- find_btf_member_offset ( type_section, str_section, task_struct_id, "thread" ) ?;
488+ let thread_info = find_btf_member_info ( type_section, str_section, task_struct_id, "thread" ) ?;
489+ let thread_offset = thread_info. offset ;
490+ let thread_type_id = thread_info. type_id ;
491+
492+ // Architecture-specific: x86_64 uses fsbase, ARM64 uses uw.tp_value
493+ let fsbase_offset = {
494+ #[ cfg( target_arch = "x86_64" ) ]
495+ {
496+ find_btf_member_offset ( type_section, str_section, thread_type_id, "fsbase" ) ?
497+ }
474498
475- // Find thread_struct type and fsbase offset within it
476- let thread_type_id = find_btf_member_type ( type_section, str_section, task_struct_id, "thread" ) ?;
477- let fsbase_offset =
478- find_btf_member_offset ( type_section, str_section, thread_type_id, "fsbase" ) ?;
499+ #[ cfg( target_arch = "aarch64" ) ]
500+ {
501+ // ARM64: thread_struct.uw.tp_value
502+ let uw_info = find_btf_member_info ( type_section, str_section, thread_type_id, "uw" ) ?;
503+ let uw_offset = uw_info. offset ;
504+ let uw_type_id = uw_info. type_id ;
505+ let tp_value_offset =
506+ find_btf_member_offset ( type_section, str_section, uw_type_id, "tp_value" ) ?;
507+ uw_offset + tp_value_offset
508+ }
509+ #[ cfg( not( any( target_arch = "x86_64" , target_arch = "aarch64" ) ) ) ]
510+ {
511+ return Err ( Error :: Msg (
512+ "TPBASE BTF parsing not supported for this architecture" . to_string ( ) ,
513+ ) ) ;
514+ }
515+ } ;
479516
480517 let total_offset = thread_offset + fsbase_offset;
481518
@@ -491,13 +528,13 @@ fn parse_btf_task_struct_fsbase(btf_data: &[u8]) -> Result<u64> {
491528}
492529
493530/// BTF type kinds
494- #[ cfg( target_arch = "x86_64" ) ]
531+ #[ cfg( any ( target_arch = "x86_64" , target_arch = "aarch64" ) ) ]
495532const BTF_KIND_STRUCT : u32 = 4 ;
496- #[ cfg( target_arch = "x86_64" ) ]
533+ #[ cfg( any ( target_arch = "x86_64" , target_arch = "aarch64" ) ) ]
497534const BTF_KIND_UNION : u32 = 5 ;
498535
499536/// Calculate extra size for a BTF type based on its kind and vlen
500- #[ cfg( target_arch = "x86_64" ) ]
537+ #[ cfg( any ( target_arch = "x86_64" , target_arch = "aarch64" ) ) ]
501538fn btf_type_extra_size ( kind : u32 , vlen : u32 ) -> usize {
502539 match kind {
503540 1 => 4 , // BTF_KIND_INT
@@ -523,7 +560,7 @@ fn btf_type_extra_size(kind: u32, vlen: u32) -> usize {
523560}
524561
525562/// Find BTF struct type ID by name
526- #[ cfg( target_arch = "x86_64" ) ]
563+ #[ cfg( any ( target_arch = "x86_64" , target_arch = "aarch64" ) ) ]
527564fn find_btf_struct_by_name ( type_section : & [ u8 ] , str_section : & [ u8 ] , name : & str ) -> Result < u32 > {
528565 // BTF type format:
529566 // struct btf_type {
@@ -575,7 +612,7 @@ fn find_btf_struct_by_name(type_section: &[u8], str_section: &[u8], name: &str)
575612}
576613
577614/// BTF member info containing both offset and type ID
578- #[ cfg( target_arch = "x86_64" ) ]
615+ #[ cfg( any ( target_arch = "x86_64" , target_arch = "aarch64" ) ) ]
579616struct BtfMemberInfo {
580617 /// Offset in bytes from the start of the struct
581618 offset : u64 ,
@@ -585,7 +622,7 @@ struct BtfMemberInfo {
585622
586623/// Find both offset and type ID of a member in a BTF struct.
587624/// This is the unified implementation that extracts all member info at once.
588- #[ cfg( target_arch = "x86_64" ) ]
625+ #[ cfg( any ( target_arch = "x86_64" , target_arch = "aarch64" ) ) ]
589626fn find_btf_member_info (
590627 type_section : & [ u8 ] ,
591628 str_section : & [ u8 ] ,
@@ -659,7 +696,7 @@ fn find_btf_member_info(
659696}
660697
661698/// Find offset of a member in a BTF struct
662- #[ cfg( target_arch = "x86_64" ) ]
699+ #[ cfg( any ( target_arch = "x86_64" , target_arch = "aarch64" ) ) ]
663700fn find_btf_member_offset (
664701 type_section : & [ u8 ] ,
665702 str_section : & [ u8 ] ,
@@ -669,19 +706,8 @@ fn find_btf_member_offset(
669706 find_btf_member_info ( type_section, str_section, struct_id, member_name) . map ( |info| info. offset )
670707}
671708
672- /// Find type ID of a member in a BTF struct
673- #[ cfg( target_arch = "x86_64" ) ]
674- fn find_btf_member_type (
675- type_section : & [ u8 ] ,
676- str_section : & [ u8 ] ,
677- struct_id : u32 ,
678- member_name : & str ,
679- ) -> Result < u32 > {
680- find_btf_member_info ( type_section, str_section, struct_id, member_name) . map ( |info| info. type_id )
681- }
682-
683709/// Get null-terminated string from BTF string section
684- #[ cfg( target_arch = "x86_64" ) ]
710+ #[ cfg( any ( target_arch = "x86_64" , target_arch = "aarch64" ) ) ]
685711fn get_btf_string ( str_section : & [ u8 ] , offset : usize ) -> & str {
686712 if offset >= str_section. len ( ) {
687713 return "" ;
0 commit comments