11use memflow:: os:: process:: * ;
22use memflow:: prelude:: v1:: * ;
33
4- use libc:: { c_int, sysctl, CTL_KERN , KERN_PROCARGS2 } ;
4+ use libc:: { c_int, size_t , sysctl, CTL_KERN , KERN_ARGMAX , KERN_PROCARGS2 } ;
55
66use libc:: { sysconf, _SC_PAGESIZE} ;
77use libproc:: {
@@ -28,6 +28,107 @@ use mem::ProcessVirtualMemory;
2828pub mod process;
2929pub use process:: MacProcess ;
3030
31+ #[ derive( Clone , Debug , Default ) ]
32+ pub ( super ) struct ProcArgs {
33+ pub exec_path : String ,
34+ pub argv : Vec < String > ,
35+ }
36+
37+ fn argmax ( ) -> usize {
38+ let mut mib: [ c_int ; 2 ] = [ CTL_KERN , KERN_ARGMAX ] ;
39+ let mut value: c_int = 0 ;
40+ let mut len = core:: mem:: size_of :: < c_int > ( ) as size_t ;
41+
42+ let ret = unsafe {
43+ sysctl (
44+ mib. as_mut_ptr ( ) ,
45+ mib. len ( ) as _ ,
46+ ( & mut value as * mut c_int ) . cast ( ) ,
47+ & mut len,
48+ core:: ptr:: null_mut ( ) ,
49+ 0 ,
50+ )
51+ } ;
52+
53+ if ret == 0 && value > 0 {
54+ value as usize
55+ } else {
56+ 4096
57+ }
58+ }
59+
60+ pub ( super ) fn read_procargs2 ( pid : Pid ) -> Result < Vec < u8 > > {
61+ let mut scratch = vec ! [ 0u8 ; argmax( ) ] ;
62+
63+ let mut mib: [ c_int ; 3 ] = [ CTL_KERN , KERN_PROCARGS2 , pid as _ ] ;
64+ let mut len = scratch. len ( ) as size_t ;
65+
66+ let ret = unsafe {
67+ sysctl (
68+ mib. as_mut_ptr ( ) ,
69+ mib. len ( ) as _ ,
70+ scratch. as_mut_ptr ( ) . cast ( ) ,
71+ & mut len,
72+ core:: ptr:: null_mut ( ) ,
73+ 0 ,
74+ )
75+ } ;
76+
77+ if ret != 0 || len < 4 {
78+ return Err ( Error ( ErrorOrigin :: OsLayer , ErrorKind :: Unknown ) ) ;
79+ }
80+
81+ scratch. truncate ( len) ;
82+ Ok ( scratch)
83+ }
84+
85+ pub ( super ) fn parse_procargs2 ( data : & [ u8 ] ) -> Result < ProcArgs > {
86+ if data. len ( ) < 4 {
87+ return Err ( Error ( ErrorOrigin :: OsLayer , ErrorKind :: Unknown ) ) ;
88+ }
89+
90+ let mut argc_buf = [ 0u8 ; 4 ] ;
91+ argc_buf. copy_from_slice ( & data[ ..4 ] ) ;
92+ let argc = u32:: from_ne_bytes ( argc_buf) as usize ;
93+ let buf = & data[ 4 ..] ;
94+
95+ let mut idx = 0usize ;
96+ while idx < buf. len ( ) && buf[ idx] != 0 {
97+ idx += 1 ;
98+ }
99+ if idx == buf. len ( ) {
100+ return Err ( Error ( ErrorOrigin :: OsLayer , ErrorKind :: Unknown ) ) ;
101+ }
102+
103+ let exec_path = String :: from_utf8_lossy ( & buf[ ..idx] ) . into_owned ( ) ;
104+
105+ while idx < buf. len ( ) && buf[ idx] == 0 {
106+ idx += 1 ;
107+ }
108+
109+ let mut argv = Vec :: new ( ) ;
110+ for _ in 0 ..argc {
111+ if idx >= buf. len ( ) {
112+ break ;
113+ }
114+
115+ let start = idx;
116+ while idx < buf. len ( ) && buf[ idx] != 0 {
117+ idx += 1 ;
118+ }
119+
120+ if idx > start {
121+ argv. push ( String :: from_utf8_lossy ( & buf[ start..idx] ) . into_owned ( ) ) ;
122+ }
123+
124+ if idx < buf. len ( ) {
125+ idx += 1 ;
126+ }
127+ }
128+
129+ Ok ( ProcArgs { exec_path, argv } )
130+ }
131+
31132fn get_arch ( ) -> ArchitectureIdent {
32133 static ARCH : OnceLock < ArchitectureIdent > = OnceLock :: new ( ) ;
33134
@@ -45,7 +146,6 @@ fn get_arch() -> ArchitectureIdent {
45146
46147pub struct MacOs {
47148 info : OsInfo ,
48- scratch : Box < [ u8 ] > ,
49149 //cached_modules: Vec<KernelModule>,
50150}
51151
@@ -59,7 +159,6 @@ impl Clone for MacOs {
59159 fn clone ( & self ) -> Self {
60160 Self {
61161 info : self . info . clone ( ) ,
62- scratch : self . scratch . clone ( ) ,
63162 //cached_modules: vec![],
64163 }
65164 }
@@ -75,8 +174,6 @@ impl Default for MacOs {
75174
76175 Self {
77176 info,
78- // TODO: call KERN_ARGMAX to figure out the actual value.
79- scratch : vec ! [ 0 ; 4096 ] . into_boxed_slice ( ) ,
80177 //cached_modules: vec![],
81178 }
82179 }
@@ -109,79 +206,34 @@ impl Os for MacOs {
109206 }
110207
111208 fn process_info_by_pid ( & mut self , pid : Pid ) -> Result < ProcessInfo > {
112- let us = std:: process:: id ( ) ;
113-
114209 let bsd_info =
115- lp:: proc_pid:: pidinfo :: < lp:: bsd_info:: BSDInfo > ( us as _ , pid as _ ) . map_err ( |e| {
210+ lp:: proc_pid:: pidinfo :: < lp:: bsd_info:: BSDInfo > ( pid as _ , 0 ) . map_err ( |e| {
116211 error ! ( "bsd_info: {e}" ) ;
117212 Error ( ErrorOrigin :: OsLayer , ErrorKind :: Unknown )
118213 } ) ?;
119214
120215 // We could use lp::proc_pid::pidpath for path, but we already get it from procargs2
121216 let ( path, command_line) : ( ReprCString , ReprCString ) = {
122- let mut name: [ c_int ; 3 ] = [ CTL_KERN , KERN_PROCARGS2 , pid as _ ] ;
123- let mut len = self . scratch . len ( ) - 4 ;
124- let ret = unsafe {
125- sysctl (
126- name. as_mut_ptr ( ) ,
127- name. len ( ) as _ ,
128- self . scratch . as_mut_ptr ( ) . cast ( ) ,
129- & mut len,
130- core:: ptr:: null_mut ( ) ,
131- 0 ,
132- )
133- } ;
134-
135- if ret != 0 {
136- len = 0 ;
137- }
138-
139- // We skip the first arg, because that is the executable path.
140- let mut num_args = u32:: from_ne_bytes ( self . scratch [ ..4 ] . try_into ( ) . unwrap ( ) ) + 1 ;
141-
142- let buf = & mut self . scratch [ 4 ..( 4 + len) ] ;
143-
144- let mut start_idx = 0 ;
145- let mut start_idx_stripped = 0 ;
146- let mut idx = 0 ;
147-
148- for ( i, b) in buf. iter_mut ( ) . enumerate ( ) {
149- if num_args == 0 {
150- break ;
217+ let fallback_path = bsd_info
218+ . pbi_comm
219+ . iter ( )
220+ . copied ( )
221+ . map ( |b| b as u8 )
222+ . take_while ( |b| * b != 0 )
223+ . collect :: < Vec < u8 > > ( ) ;
224+ let fallback_path = String :: from_utf8_lossy ( & fallback_path) . into_owned ( ) ;
225+
226+ match read_procargs2 ( pid) . and_then ( |d| parse_procargs2 ( & d) ) {
227+ Ok ( parsed) => {
228+ let path = if parsed. exec_path . is_empty ( ) {
229+ fallback_path. as_str ( )
230+ } else {
231+ parsed. exec_path . as_str ( )
232+ } ;
233+ ( path. into ( ) , parsed. argv . join ( " " ) . into ( ) )
151234 }
152-
153- if * b == 0 {
154- * b = b' ' ;
155- num_args -= 1 ;
156- if start_idx == 0 {
157- start_idx = i + 1 ;
158- start_idx_stripped = i + 1 ;
159- } else if start_idx_stripped == i {
160- num_args += 1 ;
161- start_idx_stripped = i + 1 ;
162- }
163- }
164-
165- idx = i;
235+ Err ( _) => ( fallback_path. into ( ) , "" . into ( ) ) ,
166236 }
167-
168- let path = if start_idx == 0 {
169- let b = bsd_info. pbi_comm . split ( |v| * v == 0 ) . next ( ) . unwrap_or ( & [ ] ) ;
170- unsafe { & * ( b as * const [ _ ] as * const [ u8 ] ) }
171- } else {
172- & buf[ ..( start_idx - 1 ) ]
173- } ;
174-
175- (
176- std:: str:: from_utf8 ( path) . unwrap_or_default ( ) . into ( ) ,
177- std:: str:: from_utf8 ( if start_idx_stripped <= idx {
178- & buf[ start_idx_stripped..idx]
179- } else {
180- & [ ]
181- } )
182- . unwrap_or_default ( )
183- . into ( ) ,
184- )
185237 } ;
186238 let name = path. split ( & [ '/' , '\\' ] [ ..] ) . last ( ) . unwrap ( ) . into ( ) ;
187239
0 commit comments