@@ -101,7 +101,7 @@ _get_base_64(Elf64_Ehdr* ehdr, void* elf_map) {
101
101
} /* _get_base_64 */
102
102
103
103
static int
104
- _py_proc__analyze_elf64 (py_proc_t * self , void * elf_map , void * elf_base ) {
104
+ _py_proc__analyze_elf64 (py_proc_t * self , void * elf_map , void * elf_base , proc_vm_map_block_t * bss ) {
105
105
register int symbols = 0 ;
106
106
107
107
Elf64_Ehdr * ehdr = elf_map ;
@@ -120,7 +120,7 @@ _py_proc__analyze_elf64(py_proc_t* self, void* elf_map, void* elf_base) {
120
120
size_t bss_size = 0 ;
121
121
122
122
if (base != UINT64_MAX ) {
123
- log_d ("Base @ %p" , base );
123
+ log_d ("ELF base @ %p" , base );
124
124
125
125
for (Elf64_Off sh_off = ehdr -> e_shoff ; sh_off < elf_map_size ; sh_off += ehdr -> e_shentsize ) {
126
126
p_shdr = (Elf64_Shdr * )(elf_map + sh_off );
@@ -136,7 +136,7 @@ _py_proc__analyze_elf64(py_proc_t* self, void* elf_map, void* elf_base) {
136
136
}
137
137
}
138
138
139
- if (p_dynsym != NULL ) {
139
+ if (isvalid ( p_dynsym ) ) {
140
140
if (p_dynsym -> sh_offset != 0 ) {
141
141
Elf64_Shdr * p_strtabsh = (Elf64_Shdr * )(elf_map + ELF_SH_OFF (ehdr , p_dynsym -> sh_link ));
142
142
@@ -162,9 +162,9 @@ _py_proc__analyze_elf64(py_proc_t* self, void* elf_map, void* elf_base) {
162
162
}
163
163
164
164
// Communicate BSS data back to the caller
165
- self -> map . bss . base = bss_base ;
166
- self -> map . bss . size = bss_size ;
167
- log_d ("BSS @ %p (size %x, offset %x)" , self -> map . bss . base , self -> map . bss . size , self -> map . bss . base - elf_base );
165
+ bss -> base = bss_base ;
166
+ bss -> size = bss_size ;
167
+ log_d ("BSS @ %p (size %x, offset %x)" , bss_base , bss_size , bss_base - elf_base );
168
168
169
169
SUCCESS ;
170
170
} /* _py_proc__analyze_elf64 */
@@ -181,7 +181,7 @@ _get_base_32(Elf32_Ehdr* ehdr, void* elf_map) {
181
181
} /* _get_base_32 */
182
182
183
183
static int
184
- _py_proc__analyze_elf32 (py_proc_t * self , void * elf_map , void * elf_base ) {
184
+ _py_proc__analyze_elf32 (py_proc_t * self , void * elf_map , void * elf_base , proc_vm_map_block_t * bss ) {
185
185
register int symbols = 0 ;
186
186
187
187
Elf32_Ehdr * ehdr = elf_map ;
@@ -200,7 +200,7 @@ _py_proc__analyze_elf32(py_proc_t* self, void* elf_map, void* elf_base) {
200
200
size_t bss_size = 0 ;
201
201
202
202
if (base != UINT32_MAX ) {
203
- log_d ("Base @ %p" , base );
203
+ log_d ("ELF base @ %p" , base );
204
204
205
205
for (Elf32_Off sh_off = ehdr -> e_shoff ; sh_off < elf_map_size ; sh_off += ehdr -> e_shentsize ) {
206
206
p_shdr = (Elf32_Shdr * )(elf_map + sh_off );
@@ -216,7 +216,7 @@ _py_proc__analyze_elf32(py_proc_t* self, void* elf_map, void* elf_base) {
216
216
}
217
217
}
218
218
219
- if (p_dynsym != NULL ) {
219
+ if (isvalid ( p_dynsym ) ) {
220
220
if (p_dynsym -> sh_offset != 0 ) {
221
221
Elf32_Shdr * p_strtabsh = (Elf32_Shdr * )(elf_map + ELF_SH_OFF (ehdr , p_dynsym -> sh_link ));
222
222
@@ -242,9 +242,9 @@ _py_proc__analyze_elf32(py_proc_t* self, void* elf_map, void* elf_base) {
242
242
}
243
243
244
244
// Communicate BSS data back to the caller
245
- self -> map . bss . base = bss_base ;
246
- self -> map . bss . size = bss_size ;
247
- log_d ("BSS @ %p (size %x, offset %x)" , self -> map . bss . base , self -> map . bss . size , self -> map . bss . base - elf_base );
245
+ bss -> base = bss_base ;
246
+ bss -> size = bss_size ;
247
+ log_d ("BSS @ %p (size %x, offset %x)" , bss_base , bss_size , bss_base - elf_base );
248
248
249
249
SUCCESS ;
250
250
} /* _py_proc__analyze_elf32 */
@@ -259,7 +259,7 @@ _elf_check(Elf64_Ehdr* ehdr) {
259
259
260
260
// ----------------------------------------------------------------------------
261
261
static int
262
- _py_proc__analyze_elf (py_proc_t * self , char * path , void * elf_base ) {
262
+ _py_proc__analyze_elf (py_proc_t * self , char * path , void * elf_base , proc_vm_map_block_t * bss ) {
263
263
cu_fd fd = open (path , O_RDONLY );
264
264
if (fd == -1 ) {
265
265
log_e ("Cannot open binary file %s" , path );
@@ -299,11 +299,11 @@ _py_proc__analyze_elf(py_proc_t* self, char* path, void* elf_base) {
299
299
switch (ehdr -> e_ident [EI_CLASS ]) {
300
300
case ELFCLASS64 :
301
301
log_d ("%s is 64-bit ELF" , path );
302
- return _py_proc__analyze_elf64 (self , binary_map -> addr , elf_base );
302
+ return _py_proc__analyze_elf64 (self , binary_map -> addr , elf_base , bss );
303
303
304
304
case ELFCLASS32 :
305
305
log_d ("%s is 32-bit ELF" , path );
306
- return _py_proc__analyze_elf32 (self , binary_map -> addr , elf_base );
306
+ return _py_proc__analyze_elf32 (self , binary_map -> addr , elf_base , bss );
307
307
308
308
default :
309
309
log_e ("%s has invalid ELF class" , path );
@@ -314,9 +314,10 @@ _py_proc__analyze_elf(py_proc_t* self, char* path, void* elf_base) {
314
314
315
315
// ----------------------------------------------------------------------------
316
316
static int
317
- _py_proc__parse_maps_file (py_proc_t * self ) {
318
- int maps_flag = 0 ;
319
- struct vm_map * map = NULL ;
317
+ _py_proc__inspect_vm_maps (py_proc_t * self ) {
318
+ int maps_flag = 0 ;
319
+ struct vm_map * map = NULL ;
320
+ proc_vm_map_block_t bss ;
320
321
321
322
cu_proc_map_t * proc_maps = proc_map_new (self -> pid );
322
323
if (!isvalid (proc_maps )) {
@@ -376,10 +377,10 @@ _py_proc__parse_maps_file(py_proc_t* self) {
376
377
map -> file_size = _file_size (map -> path );
377
378
map -> base = first_binary_map -> address ;
378
379
map -> size = first_binary_map -> size ;
379
- map -> has_symbols = success (_py_proc__analyze_elf (self , map -> path , map -> base ));
380
+ map -> has_symbols = success (_py_proc__analyze_elf (self , map -> path , map -> base , & bss ));
380
381
if (map -> has_symbols ) {
381
- map -> bss_base = self -> map . bss .base ;
382
- map -> bss_size = self -> map . bss .size ;
382
+ map -> bss_base = bss .base ;
383
+ map -> bss_size = bss .size ;
383
384
}
384
385
log_d ("Binary path: %s (symbols: %d)" , map -> path , map -> has_symbols );
385
386
@@ -413,7 +414,7 @@ _py_proc__parse_maps_file(py_proc_t* self) {
413
414
414
415
proc_map_t * first_lib_map = proc_map__first_submatch (proc_maps , LIB_NEEDLE );
415
416
if (isvalid (first_lib_map )) {
416
- if (success (_py_proc__analyze_elf (self , first_lib_map -> pathname , first_lib_map -> address ))) {
417
+ if (success (_py_proc__analyze_elf (self , first_lib_map -> pathname , first_lib_map -> address , & bss ))) {
417
418
// The library binary has symbols
418
419
map = & (pd -> maps [MAP_LIBSYM ]);
419
420
@@ -427,8 +428,8 @@ _py_proc__parse_maps_file(py_proc_t* self) {
427
428
map -> base = first_lib_map -> address ;
428
429
map -> size = first_lib_map -> size ;
429
430
map -> has_symbols = TRUE;
430
- map -> bss_base = self -> map . bss .base ;
431
- map -> bss_size = self -> map . bss .size ;
431
+ map -> bss_base = bss .base ;
432
+ map -> bss_size = bss .size ;
432
433
433
434
log_d ("Library path: %s (with symbols)" , map -> path );
434
435
} else {
@@ -512,7 +513,7 @@ _py_proc__parse_maps_file(py_proc_t* self) {
512
513
log_d ("VM maps parsing result: bin=%s lib=%s flags=%d" , self -> bin_path , self -> lib_path , maps_flag );
513
514
514
515
SUCCESS ;
515
- } /* _py_proc__parse_maps_file */
516
+ } /* _py_proc__inspect_vm_maps */
516
517
517
518
// ----------------------------------------------------------------------------
518
519
static ssize_t
@@ -536,21 +537,21 @@ _py_proc__get_resident_memory(py_proc_t* self) {
536
537
537
538
#ifdef NATIVE
538
539
// ----------------------------------------------------------------------------
540
+ #define RANGES_MAX 256
541
+
539
542
char pathname [1024 ];
540
543
char prevpathname [1024 ];
541
- vm_range_t * ranges [256 ];
544
+ vm_range_t * ranges [RANGES_MAX ];
542
545
543
546
static int
544
547
_py_proc__get_vm_maps (py_proc_t * self ) {
545
- cu_FILE * fp = NULL ;
546
- cu_char * line = NULL ;
547
- size_t len = 0 ;
548
548
vm_range_tree_t * tree = NULL ;
549
549
hash_table_t * table = NULL ;
550
+ cu_proc_map_t * maps = NULL ;
550
551
551
552
if (pargs .where ) {
552
553
tree = vm_range_tree_new ();
553
- table = hash_table_new (256 );
554
+ table = hash_table_new (RANGES_MAX );
554
555
555
556
vm_range_tree__destroy (self -> maps_tree );
556
557
hash_table__destroy (self -> base_table );
@@ -559,36 +560,40 @@ _py_proc__get_vm_maps(py_proc_t* self) {
559
560
self -> base_table = table ;
560
561
}
561
562
562
- fp = _procfs (self -> pid , "maps" );
563
- if (!isvalid (fp )) {
563
+ maps = proc_map_new (self -> pid );
564
+ if (!isvalid (maps )) {
564
565
set_error (EPROC );
565
566
FAIL ;
566
567
}
567
568
568
569
log_d ("Rebuilding vm ranges tree" );
569
570
570
571
int nrange = 0 ;
571
- while ( getline ( & line , & len , fp ) != -1 && nrange < 256 ) {
572
- ssize_t lower , upper ;
573
-
574
- if ( sscanf (
575
- line , ADDR_FMT "-" ADDR_FMT " %*s %*x %*x:%*x %*x %s\n" , & lower , & upper , // Map bounds
576
- pathname // Binary path
577
- ) == 3
578
- && pathname [ 0 ] != '[' ) {
579
- if ( pargs . where ) {
580
- if (strcmp ( pathname , prevpathname ) ) {
581
- ranges [ nrange ++ ] = vm_range_new ( lower , upper , strdup ( pathname ));
582
- key_dt key = string__hash ( pathname );
583
- if (! isvalid ( hash_table__get ( table , key )))
584
- hash_table__set ( table , key , ( value_t ) lower );
585
- strcpy ( prevpathname , pathname );
586
- } else
587
- ranges [ nrange - 1 ] -> hi = upper ;
572
+ PROC_MAP_ITER ( maps , m ) {
573
+ if ( nrange >= RANGES_MAX ) {
574
+ log_e ( "Too many ranges" );
575
+ break ;
576
+ }
577
+
578
+ if (! isvalid ( m -> pathname ))
579
+ continue ;
580
+
581
+ if (pargs . where ) {
582
+ if ( strcmp ( m -> pathname , prevpathname )) {
583
+ ranges [ nrange ++ ]
584
+ = vm_range_new (( addr_t ) m -> address , (( addr_t ) m -> address ) + m -> size , strdup ( m -> pathname ));
585
+ key_dt key = string__hash ( m -> pathname );
586
+ if (! isvalid ( hash_table__get ( table , key )))
587
+ hash_table__set ( table , key , ( value_t ) m -> address );
588
+ strcpy ( prevpathname , m -> pathname ) ;
588
589
} else
589
- // We print the maps instead so that we can resolve them later and use
590
- // the CPU more efficiently to collect samples.
591
- emit_metadata ("map" , ADDR_FMT "-" ADDR_FMT " %s" , lower , upper , pathname );
590
+ ranges [nrange - 1 ]-> hi = ((addr_t )m -> address ) + m -> size ;
591
+ } else {
592
+ // We print the maps instead so that we can resolve them later and use
593
+ // the CPU more efficiently to collect samples.
594
+ emit_metadata (
595
+ "map" , ADDR_FMT "-" ADDR_FMT " %s" , (addr_t )m -> address , ((addr_t )m -> address ) + m -> size , m -> pathname
596
+ );
592
597
}
593
598
}
594
599
@@ -602,7 +607,7 @@ _py_proc__get_vm_maps(py_proc_t* self) {
602
607
// ----------------------------------------------------------------------------
603
608
static int
604
609
_py_proc__init (py_proc_t * self ) {
605
- if (!isvalid (self ) || fail (_py_proc__parse_maps_file (self ))) {
610
+ if (!isvalid (self ) || fail (_py_proc__inspect_vm_maps (self ))) {
606
611
set_error (EPROC );
607
612
FAIL ;
608
613
}
0 commit comments