1 2 /*--------------------------------------------------------------------*/ 3 /*--- The address space manager: segment initialisation and ---*/ 4 /*--- tracking, stack operations ---*/ 5 /*--- ---*/ 6 /*--- Implementation for Linux (and Darwin!) m_aspacemgr-linux.c ---*/ 7 /*--------------------------------------------------------------------*/ 8 9 /* 10 This file is part of Valgrind, a dynamic binary instrumentation 11 framework. 12 13 Copyright (C) 2000-2012 Julian Seward 14 jseward (at) acm.org 15 16 This program is free software; you can redistribute it and/or 17 modify it under the terms of the GNU General Public License as 18 published by the Free Software Foundation; either version 2 of the 19 License, or (at your option) any later version. 20 21 This program is distributed in the hope that it will be useful, but 22 WITHOUT ANY WARRANTY; without even the implied warranty of 23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24 General Public License for more details. 25 26 You should have received a copy of the GNU General Public License 27 along with this program; if not, write to the Free Software 28 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 29 02111-1307, USA. 30 31 The GNU General Public License is contained in the file COPYING. 32 */ 33 34 #if defined(VGO_linux) || defined(VGO_darwin) 35 36 /* ************************************************************* 37 DO NOT INCLUDE ANY OTHER FILES HERE. 38 ADD NEW INCLUDES ONLY TO priv_aspacemgr.h 39 AND THEN ONLY AFTER READING DIRE WARNINGS THERE TOO. 40 ************************************************************* */ 41 42 #include "priv_aspacemgr.h" 43 #include "config.h" 44 45 46 /* Note: many of the exported functions implemented below are 47 described more fully in comments in pub_core_aspacemgr.h. 48 */ 49 50 51 /*-----------------------------------------------------------------*/ 52 /*--- ---*/ 53 /*--- Overview. ---*/ 54 /*--- ---*/ 55 /*-----------------------------------------------------------------*/ 56 57 /* Purpose 58 ~~~~~~~ 59 The purpose of the address space manager (aspacem) is: 60 61 (1) to record the disposition of all parts of the process' address 62 space at all times. 63 64 (2) to the extent that it can, influence layout in ways favourable 65 to our purposes. 66 67 It is important to appreciate that whilst it can and does attempt 68 to influence layout, and usually succeeds, it isn't possible to 69 impose absolute control: in the end, the kernel is the final 70 arbiter, and can always bounce our requests. 71 72 Strategy 73 ~~~~~~~~ 74 The strategy is therefore as follows: 75 76 * Track ownership of mappings. Each one can belong either to 77 Valgrind or to the client. 78 79 * Try to place the client's fixed and hinted mappings at the 80 requested addresses. Fixed mappings are allowed anywhere except 81 in areas reserved by Valgrind; the client can trash its own 82 mappings if it wants. Hinted mappings are allowed providing they 83 fall entirely in free areas; if not, they will be placed by 84 aspacem in a free area. 85 86 * Anonymous mappings are allocated so as to keep Valgrind and 87 client areas widely separated when possible. If address space 88 runs low, then they may become intermingled: aspacem will attempt 89 to use all possible space. But under most circumstances lack of 90 address space is not a problem and so the areas will remain far 91 apart. 92 93 Searches for client space start at aspacem_cStart and will wrap 94 around the end of the available space if needed. Searches for 95 Valgrind space start at aspacem_vStart and will also wrap around. 96 Because aspacem_cStart is approximately at the start of the 97 available space and aspacem_vStart is approximately in the 98 middle, for the most part the client anonymous mappings will be 99 clustered towards the start of available space, and Valgrind ones 100 in the middle. 101 102 The available space is delimited by aspacem_minAddr and 103 aspacem_maxAddr. aspacem is flexible and can operate with these 104 at any (sane) setting. For 32-bit Linux, aspacem_minAddr is set 105 to some low-ish value at startup (64M) and aspacem_maxAddr is 106 derived from the stack pointer at system startup. This seems a 107 reliable way to establish the initial boundaries. 108 109 64-bit Linux is similar except for the important detail that the 110 upper boundary is set to 32G. The reason is so that all 111 anonymous mappings (basically all client data areas) are kept 112 below 32G, since that is the maximum range that memcheck can 113 track shadow memory using a fast 2-level sparse array. It can go 114 beyond that but runs much more slowly. The 32G limit is 115 arbitrary and is trivially changed. So, with the current 116 settings, programs on 64-bit Linux will appear to run out of 117 address space and presumably fail at the 32G limit. Given the 118 9/8 space overhead of Memcheck, that means you should be able to 119 memcheckify programs that use up to about 14G natively. 120 121 Note that the aspacem_minAddr/aspacem_maxAddr limits apply only to 122 anonymous mappings. The client can still do fixed and hinted maps 123 at any addresses provided they do not overlap Valgrind's segments. 124 This makes Valgrind able to load prelinked .so's at their requested 125 addresses on 64-bit platforms, even if they are very high (eg, 126 112TB). 127 128 At startup, aspacem establishes the usable limits, and advises 129 m_main to place the client stack at the top of the range, which on 130 a 32-bit machine will be just below the real initial stack. One 131 effect of this is that self-hosting sort-of works, because an inner 132 valgrind will then place its client's stack just below its own 133 initial stack. 134 135 The segment array and segment kinds 136 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 137 The central data structure is the segment array (segments[0 138 .. nsegments_used-1]). This covers the entire address space in 139 order, giving account of every byte of it. Free spaces are 140 represented explicitly as this makes many operations simpler. 141 Mergeable adjacent segments are aggressively merged so as to create 142 a "normalised" representation (preen_nsegments). 143 144 There are 7 (mutually-exclusive) segment kinds, the meaning of 145 which is important: 146 147 SkFree: a free space, which may be allocated either to Valgrind (V) 148 or the client (C). 149 150 SkAnonC: an anonymous mapping belonging to C. For these, aspacem 151 tracks a boolean indicating whether or not is is part of the 152 client's heap area (can't remember why). 153 154 SkFileC: a file mapping belonging to C. 155 156 SkShmC: a shared memory segment belonging to C. 157 158 SkAnonV: an anonymous mapping belonging to V. These cover all V's 159 dynamic memory needs, including non-client malloc/free areas, 160 shadow memory, and the translation cache. 161 162 SkFileV: a file mapping belonging to V. As far as I know these are 163 only created transiently for the purposes of reading debug info. 164 165 SkResvn: a reservation segment. 166 167 These are mostly straightforward. Reservation segments have some 168 subtlety, however. 169 170 A reservation segment is unmapped from the kernel's point of view, 171 but is an area in which aspacem will not create anonymous maps 172 (either Vs or Cs). The idea is that we will try to keep it clear 173 when the choice to do so is ours. Reservation segments are 174 'invisible' from the client's point of view: it may choose to park 175 a fixed mapping in the middle of one, and that's just tough -- we 176 can't do anything about that. From the client's perspective 177 reservations are semantically equivalent to (although 178 distinguishable from, if it makes enquiries) free areas. 179 180 Reservations are a primitive mechanism provided for whatever 181 purposes the rest of the system wants. Currently they are used to 182 reserve the expansion space into which a growdown stack is 183 expanded, and into which the data segment is extended. Note, 184 though, those uses are entirely external to this module, which only 185 supplies the primitives. 186 187 Reservations may be shrunk in order that an adjoining anonymous 188 mapping may be extended. This makes dataseg/stack expansion work. 189 A reservation may not be shrunk below one page. 190 191 The advise/notify concept 192 ~~~~~~~~~~~~~~~~~~~~~~~~~ 193 All mmap-related calls must be routed via aspacem. Calling 194 sys_mmap directly from the rest of the system is very dangerous 195 because aspacem's data structures will become out of date. 196 197 The fundamental mode of operation of aspacem is to support client 198 mmaps. Here's what happens (in ML_(generic_PRE_sys_mmap)): 199 200 * m_syswrap intercepts the mmap call. It examines the parameters 201 and identifies the requested placement constraints. There are 202 three possibilities: no constraint (MAny), hinted (MHint, "I 203 prefer X but will accept anything"), and fixed (MFixed, "X or 204 nothing"). 205 206 * This request is passed to VG_(am_get_advisory). This decides on 207 a placement as described in detail in Strategy above. It may 208 also indicate that the map should fail, because it would trash 209 one of Valgrind's areas, which would probably kill the system. 210 211 * Control returns to the wrapper. If VG_(am_get_advisory) has 212 declared that the map should fail, then it must be made to do so. 213 Usually, though, the request is considered acceptable, in which 214 case an "advised" address is supplied. The advised address 215 replaces the original address supplied by the client, and 216 MAP_FIXED is set. 217 218 Note at this point that although aspacem has been asked for 219 advice on where to place the mapping, no commitment has yet been 220 made by either it or the kernel. 221 222 * The adjusted request is handed off to the kernel. 223 224 * The kernel's result is examined. If the map succeeded, aspacem 225 is told of the outcome (VG_(am_notify_client_mmap)), so it can 226 update its records accordingly. 227 228 This then is the central advise-notify idiom for handling client 229 mmap/munmap/mprotect/shmat: 230 231 * ask aspacem for an advised placement (or a veto) 232 233 * if not vetoed, hand request to kernel, using the advised placement 234 235 * examine result, and if successful, notify aspacem of the result. 236 237 There are also many convenience functions, eg 238 VG_(am_mmap_anon_fixed_client), which do both phases entirely within 239 aspacem. 240 241 To debug all this, a sync-checker is provided. It reads 242 /proc/self/maps, compares what it sees with aspacem's records, and 243 complains if there is a difference. --sanity-level=3 runs it before 244 and after each syscall, which is a powerful, if slow way of finding 245 buggy syscall wrappers. 246 247 Loss of pointercheck 248 ~~~~~~~~~~~~~~~~~~~~ 249 Up to and including Valgrind 2.4.1, x86 segmentation was used to 250 enforce seperation of V and C, so that wild writes by C could not 251 trash V. This got called "pointercheck". Unfortunately, the new 252 more flexible memory layout, plus the need to be portable across 253 different architectures, means doing this in hardware is no longer 254 viable, and doing it in software is expensive. So at the moment we 255 don't do it at all. 256 */ 257 258 259 /*-----------------------------------------------------------------*/ 260 /*--- ---*/ 261 /*--- The Address Space Manager's state. ---*/ 262 /*--- ---*/ 263 /*-----------------------------------------------------------------*/ 264 265 /* ------ start of STATE for the address-space manager ------ */ 266 267 /* Max number of segments we can track. */ 268 #define VG_N_SEGMENTS 5000 269 270 /* Max number of segment file names we can track. */ 271 #define VG_N_SEGNAMES 1000 272 273 /* Max length of a segment file name. */ 274 #define VG_MAX_SEGNAMELEN 1000 275 276 277 typedef 278 struct { 279 Bool inUse; 280 Bool mark; 281 HChar fname[VG_MAX_SEGNAMELEN]; 282 } 283 SegName; 284 285 /* Filename table. _used is the high water mark; an entry is only 286 valid if its index >= 0, < _used, and its .inUse field == True. 287 The .mark field is used to garbage-collect dead entries. 288 */ 289 static SegName segnames[VG_N_SEGNAMES]; 290 static Int segnames_used = 0; 291 292 293 /* Array [0 .. nsegments_used-1] of all mappings. */ 294 /* Sorted by .addr field. */ 295 /* I: len may not be zero. */ 296 /* I: overlapping segments are not allowed. */ 297 /* I: the segments cover the entire address space precisely. */ 298 /* Each segment can optionally hold an index into the filename table. */ 299 300 static NSegment nsegments[VG_N_SEGMENTS]; 301 static Int nsegments_used = 0; 302 303 #define Addr_MIN ((Addr)0) 304 #define Addr_MAX ((Addr)(-1ULL)) 305 306 /* Limits etc */ 307 308 // The smallest address that aspacem will try to allocate 309 static Addr aspacem_minAddr = 0; 310 311 // The largest address that aspacem will try to allocate 312 static Addr aspacem_maxAddr = 0; 313 314 // Where aspacem will start looking for client space 315 static Addr aspacem_cStart = 0; 316 317 // Where aspacem will start looking for Valgrind space 318 static Addr aspacem_vStart = 0; 319 320 321 #define AM_SANITY_CHECK \ 322 do { \ 323 if (VG_(clo_sanity_level >= 3)) \ 324 aspacem_assert(VG_(am_do_sync_check) \ 325 (__PRETTY_FUNCTION__,__FILE__,__LINE__)); \ 326 } while (0) 327 328 /* ------ end of STATE for the address-space manager ------ */ 329 330 /* ------ Forwards decls ------ */ 331 inline 332 static Int find_nsegment_idx ( Addr a ); 333 334 static void parse_procselfmaps ( 335 void (*record_mapping)( Addr addr, SizeT len, UInt prot, 336 ULong dev, ULong ino, Off64T offset, 337 const UChar* filename ), 338 void (*record_gap)( Addr addr, SizeT len ) 339 ); 340 341 /* ----- Hacks to do with the "commpage" on arm-linux ----- */ 342 /* Not that I have anything against the commpage per se. It's just 343 that it's not listed in /proc/self/maps, which is a royal PITA -- 344 we have to fake it up, in parse_procselfmaps. 345 346 But note also bug 254556 comment #2: this is now fixed in newer 347 kernels -- it is listed as a "[vectors]" entry. Presumably the 348 fake entry made here duplicates the [vectors] entry, and so, if at 349 some point in the future, we can stop supporting buggy kernels, 350 then this kludge can be removed entirely, since the procmap parser 351 below will read that entry in the normal way. */ 352 #if defined(VGP_arm_linux) 353 # define ARM_LINUX_FAKE_COMMPAGE_START 0xFFFF0000 354 # define ARM_LINUX_FAKE_COMMPAGE_END1 0xFFFF1000 355 #endif 356 357 358 /*-----------------------------------------------------------------*/ 359 /*--- ---*/ 360 /*--- SegName array management. ---*/ 361 /*--- ---*/ 362 /*-----------------------------------------------------------------*/ 363 364 /* Searches the filename table to find an index for the given name. 365 If none is found, an index is allocated and the name stored. If no 366 space is available we just give up. If the string is too long to 367 store, return -1. 368 */ 369 static Int allocate_segname ( const HChar* name ) 370 { 371 Int i, j, len; 372 373 aspacem_assert(name); 374 375 if (0) VG_(debugLog)(0,"aspacem","allocate_segname %s\n", name); 376 377 len = VG_(strlen)(name); 378 if (len >= VG_MAX_SEGNAMELEN-1) { 379 return -1; 380 } 381 382 /* first see if we already have the name. */ 383 for (i = 0; i < segnames_used; i++) { 384 if (!segnames[i].inUse) 385 continue; 386 if (0 == VG_(strcmp)(name, &segnames[i].fname[0])) { 387 return i; 388 } 389 } 390 391 /* no we don't. So look for a free slot. */ 392 for (i = 0; i < segnames_used; i++) 393 if (!segnames[i].inUse) 394 break; 395 396 if (i == segnames_used) { 397 /* no free slots .. advance the high-water mark. */ 398 if (segnames_used+1 < VG_N_SEGNAMES) { 399 i = segnames_used; 400 segnames_used++; 401 } else { 402 ML_(am_barf_toolow)("VG_N_SEGNAMES"); 403 } 404 } 405 406 /* copy it in */ 407 segnames[i].inUse = True; 408 for (j = 0; j < len; j++) 409 segnames[i].fname[j] = name[j]; 410 aspacem_assert(len < VG_MAX_SEGNAMELEN); 411 segnames[i].fname[len] = 0; 412 return i; 413 } 414 415 416 /*-----------------------------------------------------------------*/ 417 /*--- ---*/ 418 /*--- Displaying the segment array. ---*/ 419 /*--- ---*/ 420 /*-----------------------------------------------------------------*/ 421 422 static HChar* show_SegKind ( SegKind sk ) 423 { 424 switch (sk) { 425 case SkFree: return " "; 426 case SkAnonC: return "anon"; 427 case SkAnonV: return "ANON"; 428 case SkFileC: return "file"; 429 case SkFileV: return "FILE"; 430 case SkShmC: return "shm "; 431 case SkResvn: return "RSVN"; 432 default: return "????"; 433 } 434 } 435 436 static HChar* show_ShrinkMode ( ShrinkMode sm ) 437 { 438 switch (sm) { 439 case SmLower: return "SmLower"; 440 case SmUpper: return "SmUpper"; 441 case SmFixed: return "SmFixed"; 442 default: return "Sm?????"; 443 } 444 } 445 446 static void show_len_concisely ( /*OUT*/HChar* buf, Addr start, Addr end ) 447 { 448 HChar* fmt; 449 ULong len = ((ULong)end) - ((ULong)start) + 1; 450 451 if (len < 10*1000*1000ULL) { 452 fmt = "%7llu"; 453 } 454 else if (len < 999999ULL * (1ULL<<20)) { 455 fmt = "%6llum"; 456 len >>= 20; 457 } 458 else if (len < 999999ULL * (1ULL<<30)) { 459 fmt = "%6llug"; 460 len >>= 30; 461 } 462 else if (len < 999999ULL * (1ULL<<40)) { 463 fmt = "%6llut"; 464 len >>= 40; 465 } 466 else { 467 fmt = "%6llue"; 468 len >>= 50; 469 } 470 ML_(am_sprintf)(buf, fmt, len); 471 } 472 473 474 /* Show full details of an NSegment */ 475 476 static void __attribute__ ((unused)) 477 show_nsegment_full ( Int logLevel, Int segNo, NSegment* seg ) 478 { 479 HChar len_buf[20]; 480 HChar* name = "(none)"; 481 482 if (seg->fnIdx >= 0 && seg->fnIdx < segnames_used 483 && segnames[seg->fnIdx].inUse 484 && segnames[seg->fnIdx].fname[0] != 0) 485 name = segnames[seg->fnIdx].fname; 486 487 show_len_concisely(len_buf, seg->start, seg->end); 488 489 VG_(debugLog)( 490 logLevel, "aspacem", 491 "%3d: %s %010llx-%010llx %s %c%c%c%c%c %s " 492 "d=0x%03llx i=%-7lld o=%-7lld (%d) m=%d %s\n", 493 segNo, show_SegKind(seg->kind), 494 (ULong)seg->start, (ULong)seg->end, len_buf, 495 seg->hasR ? 'r' : '-', seg->hasW ? 'w' : '-', 496 seg->hasX ? 'x' : '-', seg->hasT ? 'T' : '-', 497 seg->isCH ? 'H' : '-', 498 show_ShrinkMode(seg->smode), 499 seg->dev, seg->ino, seg->offset, seg->fnIdx, 500 (Int)seg->mark, name 501 ); 502 } 503 504 505 /* Show an NSegment in a user-friendly-ish way. */ 506 507 static void show_nsegment ( Int logLevel, Int segNo, NSegment* seg ) 508 { 509 HChar len_buf[20]; 510 show_len_concisely(len_buf, seg->start, seg->end); 511 512 switch (seg->kind) { 513 514 case SkFree: 515 VG_(debugLog)( 516 logLevel, "aspacem", 517 "%3d: %s %010llx-%010llx %s\n", 518 segNo, show_SegKind(seg->kind), 519 (ULong)seg->start, (ULong)seg->end, len_buf 520 ); 521 break; 522 523 case SkAnonC: case SkAnonV: case SkShmC: 524 VG_(debugLog)( 525 logLevel, "aspacem", 526 "%3d: %s %010llx-%010llx %s %c%c%c%c%c\n", 527 segNo, show_SegKind(seg->kind), 528 (ULong)seg->start, (ULong)seg->end, len_buf, 529 seg->hasR ? 'r' : '-', seg->hasW ? 'w' : '-', 530 seg->hasX ? 'x' : '-', seg->hasT ? 'T' : '-', 531 seg->isCH ? 'H' : '-' 532 ); 533 break; 534 535 case SkFileC: case SkFileV: 536 VG_(debugLog)( 537 logLevel, "aspacem", 538 "%3d: %s %010llx-%010llx %s %c%c%c%c%c d=0x%03llx " 539 "i=%-7lld o=%-7lld (%d)\n", 540 segNo, show_SegKind(seg->kind), 541 (ULong)seg->start, (ULong)seg->end, len_buf, 542 seg->hasR ? 'r' : '-', seg->hasW ? 'w' : '-', 543 seg->hasX ? 'x' : '-', seg->hasT ? 'T' : '-', 544 seg->isCH ? 'H' : '-', 545 seg->dev, seg->ino, seg->offset, seg->fnIdx 546 ); 547 break; 548 549 case SkResvn: 550 VG_(debugLog)( 551 logLevel, "aspacem", 552 "%3d: %s %010llx-%010llx %s %c%c%c%c%c %s\n", 553 segNo, show_SegKind(seg->kind), 554 (ULong)seg->start, (ULong)seg->end, len_buf, 555 seg->hasR ? 'r' : '-', seg->hasW ? 'w' : '-', 556 seg->hasX ? 'x' : '-', seg->hasT ? 'T' : '-', 557 seg->isCH ? 'H' : '-', 558 show_ShrinkMode(seg->smode) 559 ); 560 break; 561 562 default: 563 VG_(debugLog)( 564 logLevel, "aspacem", 565 "%3d: ???? UNKNOWN SEGMENT KIND\n", 566 segNo 567 ); 568 break; 569 } 570 } 571 572 /* Print out the segment array (debugging only!). */ 573 void VG_(am_show_nsegments) ( Int logLevel, HChar* who ) 574 { 575 Int i; 576 VG_(debugLog)(logLevel, "aspacem", 577 "<<< SHOW_SEGMENTS: %s (%d segments, %d segnames)\n", 578 who, nsegments_used, segnames_used); 579 for (i = 0; i < segnames_used; i++) { 580 if (!segnames[i].inUse) 581 continue; 582 VG_(debugLog)(logLevel, "aspacem", 583 "(%2d) %s\n", i, segnames[i].fname); 584 } 585 for (i = 0; i < nsegments_used; i++) 586 show_nsegment( logLevel, i, &nsegments[i] ); 587 VG_(debugLog)(logLevel, "aspacem", 588 ">>>\n"); 589 } 590 591 592 /* Get the filename corresponding to this segment, if known and if it 593 has one. The returned name's storage cannot be assumed to be 594 persistent, so the caller should immediately copy the name 595 elsewhere. */ 596 HChar* VG_(am_get_filename)( NSegment const * seg ) 597 { 598 Int i; 599 aspacem_assert(seg); 600 i = seg->fnIdx; 601 if (i < 0 || i >= segnames_used || !segnames[i].inUse) 602 return NULL; 603 else 604 return &segnames[i].fname[0]; 605 } 606 607 /* Collect up the start addresses of all non-free, non-resvn segments. 608 The interface is a bit strange in order to avoid potential 609 segment-creation races caused by dynamic allocation of the result 610 buffer *starts. 611 612 The function first computes how many entries in the result 613 buffer *starts will be needed. If this number <= nStarts, 614 they are placed in starts[0..], and the number is returned. 615 If nStarts is not large enough, nothing is written to 616 starts[0..], and the negation of the size is returned. 617 618 Correct use of this function may mean calling it multiple times in 619 order to establish a suitably-sized buffer. */ 620 621 Int VG_(am_get_segment_starts)( Addr* starts, Int nStarts ) 622 { 623 Int i, j, nSegs; 624 625 /* don't pass dumbass arguments */ 626 aspacem_assert(nStarts >= 0); 627 628 nSegs = 0; 629 for (i = 0; i < nsegments_used; i++) { 630 if (nsegments[i].kind == SkFree || nsegments[i].kind == SkResvn) 631 continue; 632 nSegs++; 633 } 634 635 if (nSegs > nStarts) { 636 /* The buffer isn't big enough. Tell the caller how big it needs 637 to be. */ 638 return -nSegs; 639 } 640 641 /* There's enough space. So write into the result buffer. */ 642 aspacem_assert(nSegs <= nStarts); 643 644 j = 0; 645 for (i = 0; i < nsegments_used; i++) { 646 if (nsegments[i].kind == SkFree || nsegments[i].kind == SkResvn) 647 continue; 648 starts[j] = nsegments[i].start; 649 j++; 650 } 651 652 aspacem_assert(j == nSegs); /* this should not fail */ 653 return nSegs; 654 } 655 656 657 /*-----------------------------------------------------------------*/ 658 /*--- ---*/ 659 /*--- Sanity checking and preening of the segment array. ---*/ 660 /*--- ---*/ 661 /*-----------------------------------------------------------------*/ 662 663 /* Check representational invariants for NSegments. */ 664 665 static Bool sane_NSegment ( NSegment* s ) 666 { 667 if (s == NULL) return False; 668 669 /* No zero sized segments and no wraparounds. */ 670 if (s->start >= s->end) return False; 671 672 /* .mark is used for admin purposes only. */ 673 if (s->mark) return False; 674 675 /* require page alignment */ 676 if (!VG_IS_PAGE_ALIGNED(s->start)) return False; 677 if (!VG_IS_PAGE_ALIGNED(s->end+1)) return False; 678 679 switch (s->kind) { 680 681 case SkFree: 682 return 683 s->smode == SmFixed 684 && s->dev == 0 && s->ino == 0 && s->offset == 0 && s->fnIdx == -1 685 && !s->hasR && !s->hasW && !s->hasX && !s->hasT 686 && !s->isCH; 687 688 case SkAnonC: case SkAnonV: case SkShmC: 689 return 690 s->smode == SmFixed 691 && s->dev == 0 && s->ino == 0 && s->offset == 0 && s->fnIdx == -1 692 && (s->kind==SkAnonC ? True : !s->isCH); 693 694 case SkFileC: case SkFileV: 695 return 696 s->smode == SmFixed 697 && (s->fnIdx == -1 || 698 (s->fnIdx >= 0 && s->fnIdx < segnames_used 699 && segnames[s->fnIdx].inUse)) 700 && !s->isCH; 701 702 case SkResvn: 703 return 704 s->dev == 0 && s->ino == 0 && s->offset == 0 && s->fnIdx == -1 705 && !s->hasR && !s->hasW && !s->hasX && !s->hasT 706 && !s->isCH; 707 708 default: 709 return False; 710 } 711 } 712 713 714 /* Try merging s2 into s1, if possible. If successful, s1 is 715 modified, and True is returned. Otherwise s1 is unchanged and 716 False is returned. */ 717 718 static Bool maybe_merge_nsegments ( NSegment* s1, NSegment* s2 ) 719 { 720 if (s1->kind != s2->kind) 721 return False; 722 723 if (s1->end+1 != s2->start) 724 return False; 725 726 /* reject cases which would cause wraparound */ 727 if (s1->start > s2->end) 728 return False; 729 730 switch (s1->kind) { 731 732 case SkFree: 733 s1->end = s2->end; 734 return True; 735 736 case SkAnonC: case SkAnonV: 737 if (s1->hasR == s2->hasR && s1->hasW == s2->hasW 738 && s1->hasX == s2->hasX && s1->isCH == s2->isCH) { 739 s1->end = s2->end; 740 s1->hasT |= s2->hasT; 741 return True; 742 } 743 break; 744 745 case SkFileC: case SkFileV: 746 if (s1->hasR == s2->hasR 747 && s1->hasW == s2->hasW && s1->hasX == s2->hasX 748 && s1->dev == s2->dev && s1->ino == s2->ino 749 && s2->offset == s1->offset 750 + ((ULong)s2->start) - ((ULong)s1->start) ) { 751 s1->end = s2->end; 752 s1->hasT |= s2->hasT; 753 return True; 754 } 755 break; 756 757 case SkShmC: 758 return False; 759 760 case SkResvn: 761 if (s1->smode == SmFixed && s2->smode == SmFixed) { 762 s1->end = s2->end; 763 return True; 764 } 765 766 default: 767 break; 768 769 } 770 771 return False; 772 } 773 774 775 /* Sanity-check and canonicalise the segment array (merge mergable 776 segments). Returns True if any segments were merged. */ 777 778 static Bool preen_nsegments ( void ) 779 { 780 Int i, j, r, w, nsegments_used_old = nsegments_used; 781 782 /* Pass 1: check the segment array covers the entire address space 783 exactly once, and also that each segment is sane. */ 784 aspacem_assert(nsegments_used > 0); 785 aspacem_assert(nsegments[0].start == Addr_MIN); 786 aspacem_assert(nsegments[nsegments_used-1].end == Addr_MAX); 787 788 aspacem_assert(sane_NSegment(&nsegments[0])); 789 for (i = 1; i < nsegments_used; i++) { 790 aspacem_assert(sane_NSegment(&nsegments[i])); 791 aspacem_assert(nsegments[i-1].end+1 == nsegments[i].start); 792 } 793 794 /* Pass 2: merge as much as possible, using 795 maybe_merge_segments. */ 796 w = 0; 797 for (r = 1; r < nsegments_used; r++) { 798 if (maybe_merge_nsegments(&nsegments[w], &nsegments[r])) { 799 /* nothing */ 800 } else { 801 w++; 802 if (w != r) 803 nsegments[w] = nsegments[r]; 804 } 805 } 806 w++; 807 aspacem_assert(w > 0 && w <= nsegments_used); 808 nsegments_used = w; 809 810 /* Pass 3: free up unused string table slots */ 811 /* clear mark bits */ 812 for (i = 0; i < segnames_used; i++) 813 segnames[i].mark = False; 814 /* mark */ 815 for (i = 0; i < nsegments_used; i++) { 816 j = nsegments[i].fnIdx; 817 aspacem_assert(j >= -1 && j < segnames_used); 818 if (j >= 0) { 819 aspacem_assert(segnames[j].inUse); 820 segnames[j].mark = True; 821 } 822 } 823 /* release */ 824 for (i = 0; i < segnames_used; i++) { 825 if (segnames[i].mark == False) { 826 segnames[i].inUse = False; 827 segnames[i].fname[0] = 0; 828 } 829 } 830 831 return nsegments_used != nsegments_used_old; 832 } 833 834 835 /* Check the segment array corresponds with the kernel's view of 836 memory layout. sync_check_ok returns True if no anomalies were 837 found, else False. In the latter case the mismatching segments are 838 displayed. 839 840 The general idea is: we get the kernel to show us all its segments 841 and also the gaps in between. For each such interval, try and find 842 a sequence of appropriate intervals in our segment array which 843 cover or more than cover the kernel's interval, and which all have 844 suitable kinds/permissions etc. 845 846 Although any specific kernel interval is not matched exactly to a 847 valgrind interval or sequence thereof, eventually any disagreement 848 on mapping boundaries will be detected. This is because, if for 849 example valgrind's intervals cover a greater range than the current 850 kernel interval, it must be the case that a neighbouring free-space 851 interval belonging to valgrind cannot cover the neighbouring 852 free-space interval belonging to the kernel. So the disagreement 853 is detected. 854 855 In other words, we examine each kernel interval in turn, and check 856 we do not disagree over the range of that interval. Because all of 857 the address space is examined, any disagreements must eventually be 858 detected. 859 */ 860 861 static Bool sync_check_ok = False; 862 863 static void sync_check_mapping_callback ( Addr addr, SizeT len, UInt prot, 864 ULong dev, ULong ino, Off64T offset, 865 const UChar* filename ) 866 { 867 Int iLo, iHi, i; 868 Bool sloppyXcheck; 869 870 /* If a problem has already been detected, don't continue comparing 871 segments, so as to avoid flooding the output with error 872 messages. */ 873 #if !defined(VGO_darwin) 874 /* GrP fixme not */ 875 if (!sync_check_ok) 876 return; 877 #endif 878 if (len == 0) 879 return; 880 881 /* The kernel should not give us wraparounds. */ 882 aspacem_assert(addr <= addr + len - 1); 883 884 iLo = find_nsegment_idx( addr ); 885 iHi = find_nsegment_idx( addr + len - 1 ); 886 887 /* These 5 should be guaranteed by find_nsegment_idx. */ 888 aspacem_assert(0 <= iLo && iLo < nsegments_used); 889 aspacem_assert(0 <= iHi && iHi < nsegments_used); 890 aspacem_assert(iLo <= iHi); 891 aspacem_assert(nsegments[iLo].start <= addr ); 892 aspacem_assert(nsegments[iHi].end >= addr + len - 1 ); 893 894 /* x86 doesn't differentiate 'x' and 'r' (at least, all except the 895 most recent NX-bit enabled CPUs) and so recent kernels attempt 896 to provide execute protection by placing all executable mappings 897 low down in the address space and then reducing the size of the 898 code segment to prevent code at higher addresses being executed. 899 900 These kernels report which mappings are really executable in 901 the /proc/self/maps output rather than mirroring what was asked 902 for when each mapping was created. In order to cope with this we 903 have a sloppyXcheck mode which we enable on x86 and s390 - in this 904 mode we allow the kernel to report execute permission when we weren't 905 expecting it but not vice versa. */ 906 # if defined(VGA_x86) || defined (VGA_s390x) 907 sloppyXcheck = True; 908 # else 909 sloppyXcheck = False; 910 # endif 911 912 /* NSegments iLo .. iHi inclusive should agree with the presented 913 data. */ 914 for (i = iLo; i <= iHi; i++) { 915 916 Bool same, cmp_offsets, cmp_devino; 917 UInt seg_prot; 918 919 /* compare the kernel's offering against ours. */ 920 same = nsegments[i].kind == SkAnonC 921 || nsegments[i].kind == SkAnonV 922 || nsegments[i].kind == SkFileC 923 || nsegments[i].kind == SkFileV 924 || nsegments[i].kind == SkShmC; 925 926 seg_prot = 0; 927 if (nsegments[i].hasR) seg_prot |= VKI_PROT_READ; 928 if (nsegments[i].hasW) seg_prot |= VKI_PROT_WRITE; 929 if (nsegments[i].hasX) seg_prot |= VKI_PROT_EXEC; 930 931 cmp_offsets 932 = nsegments[i].kind == SkFileC || nsegments[i].kind == SkFileV; 933 934 cmp_devino 935 = nsegments[i].dev != 0 || nsegments[i].ino != 0; 936 937 /* Consider other reasons to not compare dev/inode */ 938 #if defined(VGO_linux) 939 /* bproc does some godawful hack on /dev/zero at process 940 migration, which changes the name of it, and its dev & ino */ 941 if (filename && 0==VG_(strcmp)(filename, "/dev/zero (deleted)")) 942 cmp_devino = False; 943 944 /* hack apparently needed on MontaVista Linux */ 945 if (filename && VG_(strstr)(filename, "/.lib-ro/")) 946 cmp_devino = False; 947 #endif 948 949 #if defined(VGO_darwin) 950 // GrP fixme kernel info doesn't have dev/inode 951 cmp_devino = False; 952 953 // GrP fixme V and kernel don't agree on offsets 954 cmp_offsets = False; 955 #endif 956 957 /* If we are doing sloppy execute permission checks then we 958 allow segment to have X permission when we weren't expecting 959 it (but not vice versa) so if the kernel reported execute 960 permission then pretend that this segment has it regardless 961 of what we were expecting. */ 962 if (sloppyXcheck && (prot & VKI_PROT_EXEC) != 0) { 963 seg_prot |= VKI_PROT_EXEC; 964 } 965 966 same = same 967 && seg_prot == prot 968 && (cmp_devino 969 ? (nsegments[i].dev == dev && nsegments[i].ino == ino) 970 : True) 971 && (cmp_offsets 972 ? nsegments[i].start-nsegments[i].offset == addr-offset 973 : True); 974 if (!same) { 975 Addr start = addr; 976 Addr end = start + len - 1; 977 HChar len_buf[20]; 978 show_len_concisely(len_buf, start, end); 979 980 sync_check_ok = False; 981 982 VG_(debugLog)( 983 0,"aspacem", 984 "segment mismatch: V's seg 1st, kernel's 2nd:\n"); 985 show_nsegment_full( 0, i, &nsegments[i] ); 986 VG_(debugLog)(0,"aspacem", 987 "...: .... %010llx-%010llx %s %c%c%c.. ....... " 988 "d=0x%03llx i=%-7lld o=%-7lld (.) m=. %s\n", 989 (ULong)start, (ULong)end, len_buf, 990 prot & VKI_PROT_READ ? 'r' : '-', 991 prot & VKI_PROT_WRITE ? 'w' : '-', 992 prot & VKI_PROT_EXEC ? 'x' : '-', 993 dev, ino, offset, filename ? (HChar*)filename : "(none)" ); 994 995 return; 996 } 997 } 998 999 /* Looks harmless. Keep going. */ 1000 return; 1001 } 1002 1003 static void sync_check_gap_callback ( Addr addr, SizeT len ) 1004 { 1005 Int iLo, iHi, i; 1006 1007 /* If a problem has already been detected, don't continue comparing 1008 segments, so as to avoid flooding the output with error 1009 messages. */ 1010 #if !defined(VGO_darwin) 1011 /* GrP fixme not */ 1012 if (!sync_check_ok) 1013 return; 1014 #endif 1015 if (len == 0) 1016 return; 1017 1018 /* The kernel should not give us wraparounds. */ 1019 aspacem_assert(addr <= addr + len - 1); 1020 1021 iLo = find_nsegment_idx( addr ); 1022 iHi = find_nsegment_idx( addr + len - 1 ); 1023 1024 /* These 5 should be guaranteed by find_nsegment_idx. */ 1025 aspacem_assert(0 <= iLo && iLo < nsegments_used); 1026 aspacem_assert(0 <= iHi && iHi < nsegments_used); 1027 aspacem_assert(iLo <= iHi); 1028 aspacem_assert(nsegments[iLo].start <= addr ); 1029 aspacem_assert(nsegments[iHi].end >= addr + len - 1 ); 1030 1031 /* NSegments iLo .. iHi inclusive should agree with the presented 1032 data. */ 1033 for (i = iLo; i <= iHi; i++) { 1034 1035 Bool same; 1036 1037 /* compare the kernel's offering against ours. */ 1038 same = nsegments[i].kind == SkFree 1039 || nsegments[i].kind == SkResvn; 1040 1041 if (!same) { 1042 Addr start = addr; 1043 Addr end = start + len - 1; 1044 HChar len_buf[20]; 1045 show_len_concisely(len_buf, start, end); 1046 1047 sync_check_ok = False; 1048 1049 VG_(debugLog)( 1050 0,"aspacem", 1051 "segment mismatch: V's gap 1st, kernel's 2nd:\n"); 1052 show_nsegment_full( 0, i, &nsegments[i] ); 1053 VG_(debugLog)(0,"aspacem", 1054 " : .... %010llx-%010llx %s\n", 1055 (ULong)start, (ULong)end, len_buf); 1056 return; 1057 } 1058 } 1059 1060 /* Looks harmless. Keep going. */ 1061 return; 1062 } 1063 1064 1065 /* Sanity check: check that Valgrind and the kernel agree on the 1066 address space layout. Prints offending segments and call point if 1067 a discrepancy is detected, but does not abort the system. Returned 1068 Bool is False if a discrepancy was found. */ 1069 1070 Bool VG_(am_do_sync_check) ( const HChar* fn, 1071 const HChar* file, Int line ) 1072 { 1073 sync_check_ok = True; 1074 if (0) 1075 VG_(debugLog)(0,"aspacem", "do_sync_check %s:%d\n", file,line); 1076 parse_procselfmaps( sync_check_mapping_callback, 1077 sync_check_gap_callback ); 1078 if (!sync_check_ok) { 1079 VG_(debugLog)(0,"aspacem", 1080 "sync check at %s:%d (%s): FAILED\n", 1081 file, line, fn); 1082 VG_(debugLog)(0,"aspacem", "\n"); 1083 1084 # if 0 1085 { 1086 HChar buf[100]; 1087 VG_(am_show_nsegments)(0,"post syncheck failure"); 1088 VG_(sprintf)(buf, "/bin/cat /proc/%d/maps", VG_(getpid)()); 1089 VG_(system)(buf); 1090 } 1091 # endif 1092 1093 } 1094 return sync_check_ok; 1095 } 1096 1097 /* Hook to allow sanity checks to be done from aspacemgr-common.c. */ 1098 void ML_(am_do_sanity_check)( void ) 1099 { 1100 AM_SANITY_CHECK; 1101 } 1102 1103 1104 /*-----------------------------------------------------------------*/ 1105 /*--- ---*/ 1106 /*--- Low level access / modification of the segment array. ---*/ 1107 /*--- ---*/ 1108 /*-----------------------------------------------------------------*/ 1109 1110 /* Binary search the interval array for a given address. Since the 1111 array covers the entire address space the search cannot fail. The 1112 _WRK function does the real work. Its caller (just below) caches 1113 the results thereof, to save time. With N_CACHE of 63 we get a hit 1114 rate exceeding 90% when running OpenOffice. 1115 1116 Re ">> 12", it doesn't matter that the page size of some targets 1117 might be different from 12. Really "(a >> 12) % N_CACHE" is merely 1118 a hash function, and the actual cache entry is always validated 1119 correctly against the selected cache entry before use. 1120 */ 1121 /* Don't call find_nsegment_idx_WRK; use find_nsegment_idx instead. */ 1122 __attribute__((noinline)) 1123 static Int find_nsegment_idx_WRK ( Addr a ) 1124 { 1125 Addr a_mid_lo, a_mid_hi; 1126 Int mid, 1127 lo = 0, 1128 hi = nsegments_used-1; 1129 while (True) { 1130 /* current unsearched space is from lo to hi, inclusive. */ 1131 if (lo > hi) { 1132 /* Not found. This can't happen. */ 1133 ML_(am_barf)("find_nsegment_idx: not found"); 1134 } 1135 mid = (lo + hi) / 2; 1136 a_mid_lo = nsegments[mid].start; 1137 a_mid_hi = nsegments[mid].end; 1138 1139 if (a < a_mid_lo) { hi = mid-1; continue; } 1140 if (a > a_mid_hi) { lo = mid+1; continue; } 1141 aspacem_assert(a >= a_mid_lo && a <= a_mid_hi); 1142 aspacem_assert(0 <= mid && mid < nsegments_used); 1143 return mid; 1144 } 1145 } 1146 1147 inline static Int find_nsegment_idx ( Addr a ) 1148 { 1149 # define N_CACHE 131 /*prime*/ 1150 static Addr cache_pageno[N_CACHE]; 1151 static Int cache_segidx[N_CACHE]; 1152 static Bool cache_inited = False; 1153 1154 static UWord n_q = 0; 1155 static UWord n_m = 0; 1156 1157 UWord ix; 1158 1159 if (LIKELY(cache_inited)) { 1160 /* do nothing */ 1161 } else { 1162 for (ix = 0; ix < N_CACHE; ix++) { 1163 cache_pageno[ix] = 0; 1164 cache_segidx[ix] = -1; 1165 } 1166 cache_inited = True; 1167 } 1168 1169 ix = (a >> 12) % N_CACHE; 1170 1171 n_q++; 1172 if (0 && 0 == (n_q & 0xFFFF)) 1173 VG_(debugLog)(0,"xxx","find_nsegment_idx: %lu %lu\n", n_q, n_m); 1174 1175 if ((a >> 12) == cache_pageno[ix] 1176 && cache_segidx[ix] >= 0 1177 && cache_segidx[ix] < nsegments_used 1178 && nsegments[cache_segidx[ix]].start <= a 1179 && a <= nsegments[cache_segidx[ix]].end) { 1180 /* hit */ 1181 /* aspacem_assert( cache_segidx[ix] == find_nsegment_idx_WRK(a) ); */ 1182 return cache_segidx[ix]; 1183 } 1184 /* miss */ 1185 n_m++; 1186 cache_segidx[ix] = find_nsegment_idx_WRK(a); 1187 cache_pageno[ix] = a >> 12; 1188 return cache_segidx[ix]; 1189 # undef N_CACHE 1190 } 1191 1192 1193 1194 /* Finds the segment containing 'a'. Only returns file/anon/resvn 1195 segments. This returns a 'NSegment const *' - a pointer to 1196 readonly data. */ 1197 NSegment const * VG_(am_find_nsegment) ( Addr a ) 1198 { 1199 Int i = find_nsegment_idx(a); 1200 aspacem_assert(i >= 0 && i < nsegments_used); 1201 aspacem_assert(nsegments[i].start <= a); 1202 aspacem_assert(a <= nsegments[i].end); 1203 if (nsegments[i].kind == SkFree) 1204 return NULL; 1205 else 1206 return &nsegments[i]; 1207 } 1208 1209 1210 /* Given a pointer to a seg, tries to figure out which one it is in 1211 nsegments[..]. Very paranoid. */ 1212 static Int segAddr_to_index ( NSegment* seg ) 1213 { 1214 Int i; 1215 if (seg < &nsegments[0] || seg >= &nsegments[nsegments_used]) 1216 return -1; 1217 i = ((UChar*)seg - (UChar*)(&nsegments[0])) / sizeof(NSegment); 1218 if (i < 0 || i >= nsegments_used) 1219 return -1; 1220 if (seg == &nsegments[i]) 1221 return i; 1222 return -1; 1223 } 1224 1225 1226 /* Find the next segment along from 'here', if it is a file/anon/resvn 1227 segment. */ 1228 NSegment const * VG_(am_next_nsegment) ( NSegment* here, Bool fwds ) 1229 { 1230 Int i = segAddr_to_index(here); 1231 if (i < 0 || i >= nsegments_used) 1232 return NULL; 1233 if (fwds) { 1234 i++; 1235 if (i >= nsegments_used) 1236 return NULL; 1237 } else { 1238 i--; 1239 if (i < 0) 1240 return NULL; 1241 } 1242 switch (nsegments[i].kind) { 1243 case SkFileC: case SkFileV: case SkShmC: 1244 case SkAnonC: case SkAnonV: case SkResvn: 1245 return &nsegments[i]; 1246 default: 1247 break; 1248 } 1249 return NULL; 1250 } 1251 1252 1253 /* Trivial fn: return the total amount of space in anonymous mappings, 1254 both for V and the client. Is used for printing stats in 1255 out-of-memory messages. */ 1256 ULong VG_(am_get_anonsize_total)( void ) 1257 { 1258 Int i; 1259 ULong total = 0; 1260 for (i = 0; i < nsegments_used; i++) { 1261 if (nsegments[i].kind == SkAnonC || nsegments[i].kind == SkAnonV) { 1262 total += (ULong)nsegments[i].end 1263 - (ULong)nsegments[i].start + 1ULL; 1264 } 1265 } 1266 return total; 1267 } 1268 1269 1270 /* Test if a piece of memory is addressable by the client with at 1271 least the "prot" protection permissions by examining the underlying 1272 segments. If freeOk is True then SkFree areas are also allowed. 1273 */ 1274 static 1275 Bool is_valid_for_client( Addr start, SizeT len, UInt prot, Bool freeOk ) 1276 { 1277 Int i, iLo, iHi; 1278 Bool needR, needW, needX; 1279 1280 if (len == 0) 1281 return True; /* somewhat dubious case */ 1282 if (start + len < start) 1283 return False; /* reject wraparounds */ 1284 1285 needR = toBool(prot & VKI_PROT_READ); 1286 needW = toBool(prot & VKI_PROT_WRITE); 1287 needX = toBool(prot & VKI_PROT_EXEC); 1288 1289 iLo = find_nsegment_idx(start); 1290 aspacem_assert(start >= nsegments[iLo].start); 1291 1292 if (start+len-1 <= nsegments[iLo].end) { 1293 /* This is a speedup hack which avoids calling find_nsegment_idx 1294 a second time when possible. It is always correct to just 1295 use the "else" clause below, but is_valid_for_client is 1296 called a lot by the leak checker, so avoiding pointless calls 1297 to find_nsegment_idx, which can be expensive, is helpful. */ 1298 iHi = iLo; 1299 } else { 1300 iHi = find_nsegment_idx(start + len - 1); 1301 } 1302 1303 for (i = iLo; i <= iHi; i++) { 1304 if ( (nsegments[i].kind == SkFileC 1305 || nsegments[i].kind == SkAnonC 1306 || nsegments[i].kind == SkShmC 1307 || (nsegments[i].kind == SkFree && freeOk) 1308 || (nsegments[i].kind == SkResvn && freeOk)) 1309 && (needR ? nsegments[i].hasR : True) 1310 && (needW ? nsegments[i].hasW : True) 1311 && (needX ? nsegments[i].hasX : True) ) { 1312 /* ok */ 1313 } else { 1314 return False; 1315 } 1316 } 1317 return True; 1318 } 1319 1320 /* Test if a piece of memory is addressable by the client with at 1321 least the "prot" protection permissions by examining the underlying 1322 segments. */ 1323 Bool VG_(am_is_valid_for_client)( Addr start, SizeT len, 1324 UInt prot ) 1325 { 1326 return is_valid_for_client( start, len, prot, False/*free not OK*/ ); 1327 } 1328 1329 /* Variant of VG_(am_is_valid_for_client) which allows free areas to 1330 be consider part of the client's addressable space. It also 1331 considers reservations to be allowable, since from the client's 1332 point of view they don't exist. */ 1333 Bool VG_(am_is_valid_for_client_or_free_or_resvn) 1334 ( Addr start, SizeT len, UInt prot ) 1335 { 1336 return is_valid_for_client( start, len, prot, True/*free is OK*/ ); 1337 } 1338 1339 1340 /* Test if a piece of memory is addressable by valgrind with at least 1341 PROT_NONE protection permissions by examining the underlying 1342 segments. */ 1343 static Bool is_valid_for_valgrind( Addr start, SizeT len ) 1344 { 1345 Int i, iLo, iHi; 1346 1347 if (len == 0) 1348 return True; /* somewhat dubious case */ 1349 if (start + len < start) 1350 return False; /* reject wraparounds */ 1351 1352 iLo = find_nsegment_idx(start); 1353 iHi = find_nsegment_idx(start + len - 1); 1354 for (i = iLo; i <= iHi; i++) { 1355 if (nsegments[i].kind == SkFileV || nsegments[i].kind == SkAnonV) { 1356 /* ok */ 1357 } else { 1358 return False; 1359 } 1360 } 1361 return True; 1362 } 1363 1364 1365 /* Returns True if any part of the address range is marked as having 1366 translations made from it. This is used to determine when to 1367 discard code, so if in doubt return True. */ 1368 1369 static Bool any_Ts_in_range ( Addr start, SizeT len ) 1370 { 1371 Int iLo, iHi, i; 1372 aspacem_assert(len > 0); 1373 aspacem_assert(start + len > start); 1374 iLo = find_nsegment_idx(start); 1375 iHi = find_nsegment_idx(start + len - 1); 1376 for (i = iLo; i <= iHi; i++) { 1377 if (nsegments[i].hasT) 1378 return True; 1379 } 1380 return False; 1381 } 1382 1383 1384 /*-----------------------------------------------------------------*/ 1385 /*--- ---*/ 1386 /*--- Modifying the segment array, and constructing segments. ---*/ 1387 /*--- ---*/ 1388 /*-----------------------------------------------------------------*/ 1389 1390 /* Split the segment containing 'a' into two, so that 'a' is 1391 guaranteed to be the start of a new segment. If 'a' is already the 1392 start of a segment, do nothing. */ 1393 1394 static void split_nsegment_at ( Addr a ) 1395 { 1396 Int i, j; 1397 1398 aspacem_assert(a > 0); 1399 aspacem_assert(VG_IS_PAGE_ALIGNED(a)); 1400 1401 i = find_nsegment_idx(a); 1402 aspacem_assert(i >= 0 && i < nsegments_used); 1403 1404 if (nsegments[i].start == a) 1405 /* 'a' is already the start point of a segment, so nothing to be 1406 done. */ 1407 return; 1408 1409 /* else we have to slide the segments upwards to make a hole */ 1410 if (nsegments_used >= VG_N_SEGMENTS) 1411 ML_(am_barf_toolow)("VG_N_SEGMENTS"); 1412 for (j = nsegments_used-1; j > i; j--) 1413 nsegments[j+1] = nsegments[j]; 1414 nsegments_used++; 1415 1416 nsegments[i+1] = nsegments[i]; 1417 nsegments[i+1].start = a; 1418 nsegments[i].end = a-1; 1419 1420 if (nsegments[i].kind == SkFileV || nsegments[i].kind == SkFileC) 1421 nsegments[i+1].offset 1422 += ((ULong)nsegments[i+1].start) - ((ULong)nsegments[i].start); 1423 1424 aspacem_assert(sane_NSegment(&nsegments[i])); 1425 aspacem_assert(sane_NSegment(&nsegments[i+1])); 1426 } 1427 1428 1429 /* Do the minimum amount of segment splitting necessary to ensure that 1430 sLo is the first address denoted by some segment and sHi is the 1431 highest address denoted by some other segment. Returns the indices 1432 of the lowest and highest segments in the range. */ 1433 1434 static 1435 void split_nsegments_lo_and_hi ( Addr sLo, Addr sHi, 1436 /*OUT*/Int* iLo, 1437 /*OUT*/Int* iHi ) 1438 { 1439 aspacem_assert(sLo < sHi); 1440 aspacem_assert(VG_IS_PAGE_ALIGNED(sLo)); 1441 aspacem_assert(VG_IS_PAGE_ALIGNED(sHi+1)); 1442 1443 if (sLo > 0) 1444 split_nsegment_at(sLo); 1445 if (sHi < sHi+1) 1446 split_nsegment_at(sHi+1); 1447 1448 *iLo = find_nsegment_idx(sLo); 1449 *iHi = find_nsegment_idx(sHi); 1450 aspacem_assert(0 <= *iLo && *iLo < nsegments_used); 1451 aspacem_assert(0 <= *iHi && *iHi < nsegments_used); 1452 aspacem_assert(*iLo <= *iHi); 1453 aspacem_assert(nsegments[*iLo].start == sLo); 1454 aspacem_assert(nsegments[*iHi].end == sHi); 1455 /* Not that I'm overly paranoid or anything, definitely not :-) */ 1456 } 1457 1458 1459 /* Add SEG to the collection, deleting/truncating any it overlaps. 1460 This deals with all the tricky cases of splitting up segments as 1461 needed. */ 1462 1463 static void add_segment ( NSegment* seg ) 1464 { 1465 Int i, iLo, iHi, delta; 1466 Bool segment_is_sane; 1467 1468 Addr sStart = seg->start; 1469 Addr sEnd = seg->end; 1470 1471 aspacem_assert(sStart <= sEnd); 1472 aspacem_assert(VG_IS_PAGE_ALIGNED(sStart)); 1473 aspacem_assert(VG_IS_PAGE_ALIGNED(sEnd+1)); 1474 1475 segment_is_sane = sane_NSegment(seg); 1476 if (!segment_is_sane) show_nsegment_full(0,-1,seg); 1477 aspacem_assert(segment_is_sane); 1478 1479 split_nsegments_lo_and_hi( sStart, sEnd, &iLo, &iHi ); 1480 1481 /* Now iLo .. iHi inclusive is the range of segment indices which 1482 seg will replace. If we're replacing more than one segment, 1483 slide those above the range down to fill the hole. */ 1484 delta = iHi - iLo; 1485 aspacem_assert(delta >= 0); 1486 if (delta > 0) { 1487 for (i = iLo; i < nsegments_used-delta; i++) 1488 nsegments[i] = nsegments[i+delta]; 1489 nsegments_used -= delta; 1490 } 1491 1492 nsegments[iLo] = *seg; 1493 1494 (void)preen_nsegments(); 1495 if (0) VG_(am_show_nsegments)(0,"AFTER preen (add_segment)"); 1496 } 1497 1498 1499 /* Clear out an NSegment record. */ 1500 1501 static void init_nsegment ( /*OUT*/NSegment* seg ) 1502 { 1503 seg->kind = SkFree; 1504 seg->start = 0; 1505 seg->end = 0; 1506 seg->smode = SmFixed; 1507 seg->dev = 0; 1508 seg->ino = 0; 1509 seg->mode = 0; 1510 seg->offset = 0; 1511 seg->fnIdx = -1; 1512 seg->hasR = seg->hasW = seg->hasX = seg->hasT = seg->isCH = False; 1513 seg->mark = False; 1514 } 1515 1516 /* Make an NSegment which holds a reservation. */ 1517 1518 static void init_resvn ( /*OUT*/NSegment* seg, Addr start, Addr end ) 1519 { 1520 aspacem_assert(start < end); 1521 aspacem_assert(VG_IS_PAGE_ALIGNED(start)); 1522 aspacem_assert(VG_IS_PAGE_ALIGNED(end+1)); 1523 init_nsegment(seg); 1524 seg->kind = SkResvn; 1525 seg->start = start; 1526 seg->end = end; 1527 } 1528 1529 1530 /*-----------------------------------------------------------------*/ 1531 /*--- ---*/ 1532 /*--- Startup, including reading /proc/self/maps. ---*/ 1533 /*--- ---*/ 1534 /*-----------------------------------------------------------------*/ 1535 1536 static void read_maps_callback ( Addr addr, SizeT len, UInt prot, 1537 ULong dev, ULong ino, Off64T offset, 1538 const UChar* filename ) 1539 { 1540 NSegment seg; 1541 init_nsegment( &seg ); 1542 seg.start = addr; 1543 seg.end = addr+len-1; 1544 seg.dev = dev; 1545 seg.ino = ino; 1546 seg.offset = offset; 1547 seg.hasR = toBool(prot & VKI_PROT_READ); 1548 seg.hasW = toBool(prot & VKI_PROT_WRITE); 1549 seg.hasX = toBool(prot & VKI_PROT_EXEC); 1550 seg.hasT = False; 1551 1552 /* Don't use the presence of a filename to decide if a segment in 1553 the initial /proc/self/maps to decide if the segment is an AnonV 1554 or FileV segment as some systems don't report the filename. Use 1555 the device and inode numbers instead. Fixes bug #124528. */ 1556 seg.kind = SkAnonV; 1557 if (dev != 0 && ino != 0) 1558 seg.kind = SkFileV; 1559 1560 # if defined(VGO_darwin) 1561 // GrP fixme no dev/ino on darwin 1562 if (offset != 0) 1563 seg.kind = SkFileV; 1564 # endif // defined(VGO_darwin) 1565 1566 # if defined(VGP_arm_linux) 1567 /* The standard handling of entries read from /proc/self/maps will 1568 cause the faked up commpage segment to have type SkAnonV, which 1569 is a problem because it contains code we want the client to 1570 execute, and so later m_translate will segfault the client when 1571 it tries to go in there. Hence change the ownership of it here 1572 to the client (SkAnonC). The least-worst kludge I could think 1573 of. */ 1574 if (addr == ARM_LINUX_FAKE_COMMPAGE_START 1575 && addr + len == ARM_LINUX_FAKE_COMMPAGE_END1 1576 && seg.kind == SkAnonV) 1577 seg.kind = SkAnonC; 1578 # endif // defined(VGP_arm_linux) 1579 1580 if (filename) 1581 seg.fnIdx = allocate_segname( filename ); 1582 1583 if (0) show_nsegment( 2,0, &seg ); 1584 add_segment( &seg ); 1585 } 1586 1587 /* Initialise the address space manager, setting up the initial 1588 segment list, and reading /proc/self/maps into it. This must 1589 be called before any other function. 1590 1591 Takes a pointer to the SP at the time V gained control. This is 1592 taken to be the highest usable address (more or less). Based on 1593 that (and general consultation of tea leaves, etc) return a 1594 suggested end address for the client's stack. */ 1595 1596 Addr VG_(am_startup) ( Addr sp_at_startup ) 1597 { 1598 NSegment seg; 1599 Addr suggested_clstack_top; 1600 1601 aspacem_assert(sizeof(Word) == sizeof(void*)); 1602 aspacem_assert(sizeof(Addr) == sizeof(void*)); 1603 aspacem_assert(sizeof(SizeT) == sizeof(void*)); 1604 aspacem_assert(sizeof(SSizeT) == sizeof(void*)); 1605 1606 /* Check that we can store the largest imaginable dev, ino and 1607 offset numbers in an NSegment. */ 1608 aspacem_assert(sizeof(seg.dev) == 8); 1609 aspacem_assert(sizeof(seg.ino) == 8); 1610 aspacem_assert(sizeof(seg.offset) == 8); 1611 aspacem_assert(sizeof(seg.mode) == 4); 1612 1613 /* Add a single interval covering the entire address space. */ 1614 init_nsegment(&seg); 1615 seg.kind = SkFree; 1616 seg.start = Addr_MIN; 1617 seg.end = Addr_MAX; 1618 nsegments[0] = seg; 1619 nsegments_used = 1; 1620 1621 #if defined(VGO_darwin) 1622 1623 # if VG_WORDSIZE == 4 1624 aspacem_minAddr = (Addr) 0x00001000; 1625 aspacem_maxAddr = (Addr) 0xffffffff; 1626 1627 aspacem_cStart = aspacem_minAddr; 1628 aspacem_vStart = 0xf0000000; // 0xc0000000..0xf0000000 available 1629 # else 1630 aspacem_minAddr = (Addr) 0x100000000; // 4GB page zero 1631 aspacem_maxAddr = (Addr) 0x7fffffffffff; 1632 1633 aspacem_cStart = aspacem_minAddr; 1634 aspacem_vStart = 0x700000000000; // 0x7000:00000000..0x7fff:5c000000 avail 1635 // 0x7fff:5c000000..0x7fff:ffe00000? is stack, dyld, shared cache 1636 # endif 1637 1638 suggested_clstack_top = -1; // ignored; Mach-O specifies its stack 1639 1640 #else 1641 1642 /* Establish address limits and block out unusable parts 1643 accordingly. */ 1644 1645 VG_(debugLog)(2, "aspacem", 1646 " sp_at_startup = 0x%010llx (supplied)\n", 1647 (ULong)sp_at_startup ); 1648 1649 aspacem_minAddr = (Addr) 0x04000000; // 64M 1650 1651 # if VG_WORDSIZE == 8 1652 aspacem_maxAddr = (Addr)0x800000000 - 1; // 32G 1653 # ifdef ENABLE_INNER 1654 { Addr cse = VG_PGROUNDDN( sp_at_startup ) - 1; 1655 if (aspacem_maxAddr > cse) 1656 aspacem_maxAddr = cse; 1657 } 1658 # endif 1659 # else 1660 aspacem_maxAddr = VG_PGROUNDDN( sp_at_startup ) - 1; 1661 # endif 1662 1663 aspacem_cStart = aspacem_minAddr; // 64M 1664 aspacem_vStart = VG_PGROUNDUP(aspacem_minAddr 1665 + (aspacem_maxAddr - aspacem_minAddr + 1) / 2); 1666 # ifdef ENABLE_INNER 1667 aspacem_vStart -= 0x10000000; // 256M 1668 # endif 1669 1670 suggested_clstack_top = aspacem_maxAddr - 16*1024*1024ULL 1671 + VKI_PAGE_SIZE; 1672 1673 #endif 1674 1675 aspacem_assert(VG_IS_PAGE_ALIGNED(aspacem_minAddr)); 1676 aspacem_assert(VG_IS_PAGE_ALIGNED(aspacem_maxAddr + 1)); 1677 aspacem_assert(VG_IS_PAGE_ALIGNED(aspacem_cStart)); 1678 aspacem_assert(VG_IS_PAGE_ALIGNED(aspacem_vStart)); 1679 aspacem_assert(VG_IS_PAGE_ALIGNED(suggested_clstack_top + 1)); 1680 1681 VG_(debugLog)(2, "aspacem", 1682 " minAddr = 0x%010llx (computed)\n", 1683 (ULong)aspacem_minAddr); 1684 VG_(debugLog)(2, "aspacem", 1685 " maxAddr = 0x%010llx (computed)\n", 1686 (ULong)aspacem_maxAddr); 1687 VG_(debugLog)(2, "aspacem", 1688 " cStart = 0x%010llx (computed)\n", 1689 (ULong)aspacem_cStart); 1690 VG_(debugLog)(2, "aspacem", 1691 " vStart = 0x%010llx (computed)\n", 1692 (ULong)aspacem_vStart); 1693 VG_(debugLog)(2, "aspacem", 1694 "suggested_clstack_top = 0x%010llx (computed)\n", 1695 (ULong)suggested_clstack_top); 1696 1697 if (aspacem_cStart > Addr_MIN) { 1698 init_resvn(&seg, Addr_MIN, aspacem_cStart-1); 1699 add_segment(&seg); 1700 } 1701 if (aspacem_maxAddr < Addr_MAX) { 1702 init_resvn(&seg, aspacem_maxAddr+1, Addr_MAX); 1703 add_segment(&seg); 1704 } 1705 1706 /* Create a 1-page reservation at the notional initial 1707 client/valgrind boundary. This isn't strictly necessary, but 1708 because the advisor does first-fit and starts searches for 1709 valgrind allocations at the boundary, this is kind of necessary 1710 in order to get it to start allocating in the right place. */ 1711 init_resvn(&seg, aspacem_vStart, aspacem_vStart + VKI_PAGE_SIZE - 1); 1712 add_segment(&seg); 1713 1714 VG_(am_show_nsegments)(2, "Initial layout"); 1715 1716 VG_(debugLog)(2, "aspacem", "Reading /proc/self/maps\n"); 1717 parse_procselfmaps( read_maps_callback, NULL ); 1718 /* NB: on arm-linux, parse_procselfmaps automagically kludges up 1719 (iow, hands to its callbacks) a description of the ARM Commpage, 1720 since that's not listed in /proc/self/maps (kernel bug IMO). We 1721 have to fake up its existence in parse_procselfmaps and not 1722 merely add it here as an extra segment, because doing the latter 1723 causes sync checking to fail: we see we have an extra segment in 1724 the segments array, which isn't listed in /proc/self/maps. 1725 Hence we must make it appear that /proc/self/maps contained this 1726 segment all along. Sigh. */ 1727 1728 VG_(am_show_nsegments)(2, "With contents of /proc/self/maps"); 1729 1730 AM_SANITY_CHECK; 1731 return suggested_clstack_top; 1732 } 1733 1734 1735 /*-----------------------------------------------------------------*/ 1736 /*--- ---*/ 1737 /*--- The core query-notify mechanism. ---*/ 1738 /*--- ---*/ 1739 /*-----------------------------------------------------------------*/ 1740 1741 /* Query aspacem to ask where a mapping should go. */ 1742 1743 Addr VG_(am_get_advisory) ( MapRequest* req, 1744 Bool forClient, 1745 /*OUT*/Bool* ok ) 1746 { 1747 /* This function implements allocation policy. 1748 1749 The nature of the allocation request is determined by req, which 1750 specifies the start and length of the request and indicates 1751 whether the start address is mandatory, a hint, or irrelevant, 1752 and by forClient, which says whether this is for the client or 1753 for V. 1754 1755 Return values: the request can be vetoed (*ok is set to False), 1756 in which case the caller should not attempt to proceed with 1757 making the mapping. Otherwise, *ok is set to True, the caller 1758 may proceed, and the preferred address at which the mapping 1759 should happen is returned. 1760 1761 Note that this is an advisory system only: the kernel can in 1762 fact do whatever it likes as far as placement goes, and we have 1763 no absolute control over it. 1764 1765 Allocations will never be granted in a reserved area. 1766 1767 The Default Policy is: 1768 1769 Search the address space for two free intervals: one of them 1770 big enough to contain the request without regard to the 1771 specified address (viz, as if it was a floating request) and 1772 the other being able to contain the request at the specified 1773 address (viz, as if were a fixed request). Then, depending on 1774 the outcome of the search and the kind of request made, decide 1775 whether the request is allowable and what address to advise. 1776 1777 The Default Policy is overriden by Policy Exception #1: 1778 1779 If the request is for a fixed client map, we are prepared to 1780 grant it providing all areas inside the request are either 1781 free, reservations, or mappings belonging to the client. In 1782 other words we are prepared to let the client trash its own 1783 mappings if it wants to. 1784 1785 The Default Policy is overriden by Policy Exception #2: 1786 1787 If the request is for a hinted client map, we are prepared to 1788 grant it providing all areas inside the request are either 1789 free or reservations. In other words we are prepared to let 1790 the client have a hinted mapping anywhere it likes provided 1791 it does not trash either any of its own mappings or any of 1792 valgrind's mappings. 1793 */ 1794 Int i, j; 1795 Addr holeStart, holeEnd, holeLen; 1796 Bool fixed_not_required; 1797 1798 Addr startPoint = forClient ? aspacem_cStart : aspacem_vStart; 1799 1800 Addr reqStart = req->rkind==MAny ? 0 : req->start; 1801 Addr reqEnd = reqStart + req->len - 1; 1802 Addr reqLen = req->len; 1803 1804 /* These hold indices for segments found during search, or -1 if not 1805 found. */ 1806 Int floatIdx = -1; 1807 Int fixedIdx = -1; 1808 1809 aspacem_assert(nsegments_used > 0); 1810 1811 if (0) { 1812 VG_(am_show_nsegments)(0,"getAdvisory"); 1813 VG_(debugLog)(0,"aspacem", "getAdvisory 0x%llx %lld\n", 1814 (ULong)req->start, (ULong)req->len); 1815 } 1816 1817 /* Reject zero-length requests */ 1818 if (req->len == 0) { 1819 *ok = False; 1820 return 0; 1821 } 1822 1823 /* Reject wraparounds */ 1824 if ((req->rkind==MFixed || req->rkind==MHint) 1825 && req->start + req->len < req->start) { 1826 *ok = False; 1827 return 0; 1828 } 1829 1830 /* ------ Implement Policy Exception #1 ------ */ 1831 1832 if (forClient && req->rkind == MFixed) { 1833 Int iLo = find_nsegment_idx(reqStart); 1834 Int iHi = find_nsegment_idx(reqEnd); 1835 Bool allow = True; 1836 for (i = iLo; i <= iHi; i++) { 1837 if (nsegments[i].kind == SkFree 1838 || nsegments[i].kind == SkFileC 1839 || nsegments[i].kind == SkAnonC 1840 || nsegments[i].kind == SkShmC 1841 || nsegments[i].kind == SkResvn) { 1842 /* ok */ 1843 } else { 1844 allow = False; 1845 break; 1846 } 1847 } 1848 if (allow) { 1849 /* Acceptable. Granted. */ 1850 *ok = True; 1851 return reqStart; 1852 } 1853 /* Not acceptable. Fail. */ 1854 *ok = False; 1855 return 0; 1856 } 1857 1858 /* ------ Implement Policy Exception #2 ------ */ 1859 1860 if (forClient && req->rkind == MHint) { 1861 Int iLo = find_nsegment_idx(reqStart); 1862 Int iHi = find_nsegment_idx(reqEnd); 1863 Bool allow = True; 1864 for (i = iLo; i <= iHi; i++) { 1865 if (nsegments[i].kind == SkFree 1866 || nsegments[i].kind == SkResvn) { 1867 /* ok */ 1868 } else { 1869 allow = False; 1870 break; 1871 } 1872 } 1873 if (allow) { 1874 /* Acceptable. Granted. */ 1875 *ok = True; 1876 return reqStart; 1877 } 1878 /* Not acceptable. Fall through to the default policy. */ 1879 } 1880 1881 /* ------ Implement the Default Policy ------ */ 1882 1883 /* Don't waste time looking for a fixed match if not requested to. */ 1884 fixed_not_required = req->rkind == MAny; 1885 1886 i = find_nsegment_idx(startPoint); 1887 1888 /* Examine holes from index i back round to i-1. Record the 1889 index first fixed hole and the first floating hole which would 1890 satisfy the request. */ 1891 for (j = 0; j < nsegments_used; j++) { 1892 1893 if (nsegments[i].kind != SkFree) { 1894 i++; 1895 if (i >= nsegments_used) i = 0; 1896 continue; 1897 } 1898 1899 holeStart = nsegments[i].start; 1900 holeEnd = nsegments[i].end; 1901 1902 /* Stay sane .. */ 1903 aspacem_assert(holeStart <= holeEnd); 1904 aspacem_assert(aspacem_minAddr <= holeStart); 1905 aspacem_assert(holeEnd <= aspacem_maxAddr); 1906 1907 /* See if it's any use to us. */ 1908 holeLen = holeEnd - holeStart + 1; 1909 1910 if (fixedIdx == -1 && holeStart <= reqStart && reqEnd <= holeEnd) 1911 fixedIdx = i; 1912 1913 if (floatIdx == -1 && holeLen >= reqLen) 1914 floatIdx = i; 1915 1916 /* Don't waste time searching once we've found what we wanted. */ 1917 if ((fixed_not_required || fixedIdx >= 0) && floatIdx >= 0) 1918 break; 1919 1920 i++; 1921 if (i >= nsegments_used) i = 0; 1922 } 1923 1924 aspacem_assert(fixedIdx >= -1 && fixedIdx < nsegments_used); 1925 if (fixedIdx >= 0) 1926 aspacem_assert(nsegments[fixedIdx].kind == SkFree); 1927 1928 aspacem_assert(floatIdx >= -1 && floatIdx < nsegments_used); 1929 if (floatIdx >= 0) 1930 aspacem_assert(nsegments[floatIdx].kind == SkFree); 1931 1932 AM_SANITY_CHECK; 1933 1934 /* Now see if we found anything which can satisfy the request. */ 1935 switch (req->rkind) { 1936 case MFixed: 1937 if (fixedIdx >= 0) { 1938 *ok = True; 1939 return req->start; 1940 } else { 1941 *ok = False; 1942 return 0; 1943 } 1944 break; 1945 case MHint: 1946 if (fixedIdx >= 0) { 1947 *ok = True; 1948 return req->start; 1949 } 1950 if (floatIdx >= 0) { 1951 *ok = True; 1952 return nsegments[floatIdx].start; 1953 } 1954 *ok = False; 1955 return 0; 1956 case MAny: 1957 if (floatIdx >= 0) { 1958 *ok = True; 1959 return nsegments[floatIdx].start; 1960 } 1961 *ok = False; 1962 return 0; 1963 default: 1964 break; 1965 } 1966 1967 /*NOTREACHED*/ 1968 ML_(am_barf)("getAdvisory: unknown request kind"); 1969 *ok = False; 1970 return 0; 1971 } 1972 1973 /* Convenience wrapper for VG_(am_get_advisory) for client floating or 1974 fixed requests. If start is zero, a floating request is issued; if 1975 nonzero, a fixed request at that address is issued. Same comments 1976 about return values apply. */ 1977 1978 Addr VG_(am_get_advisory_client_simple) ( Addr start, SizeT len, 1979 /*OUT*/Bool* ok ) 1980 { 1981 MapRequest mreq; 1982 mreq.rkind = start==0 ? MAny : MFixed; 1983 mreq.start = start; 1984 mreq.len = len; 1985 return VG_(am_get_advisory)( &mreq, True/*forClient*/, ok ); 1986 } 1987 1988 /* Similar to VG_(am_find_nsegment) but only returns free segments. */ 1989 static NSegment const * VG_(am_find_free_nsegment) ( Addr a ) 1990 { 1991 Int i = find_nsegment_idx(a); 1992 aspacem_assert(i >= 0 && i < nsegments_used); 1993 aspacem_assert(nsegments[i].start <= a); 1994 aspacem_assert(a <= nsegments[i].end); 1995 if (nsegments[i].kind == SkFree) 1996 return &nsegments[i]; 1997 else 1998 return NULL; 1999 } 2000 2001 Bool VG_(am_covered_by_single_free_segment) 2002 ( Addr start, SizeT len) 2003 { 2004 NSegment const* segLo = VG_(am_find_free_nsegment)( start ); 2005 NSegment const* segHi = VG_(am_find_free_nsegment)( start + len - 1 ); 2006 2007 return segLo != NULL && segHi != NULL && segLo == segHi; 2008 } 2009 2010 2011 /* Notifies aspacem that the client completed an mmap successfully. 2012 The segment array is updated accordingly. If the returned Bool is 2013 True, the caller should immediately discard translations from the 2014 specified address range. */ 2015 2016 Bool 2017 VG_(am_notify_client_mmap)( Addr a, SizeT len, UInt prot, UInt flags, 2018 Int fd, Off64T offset ) 2019 { 2020 HChar buf[VKI_PATH_MAX]; 2021 ULong dev, ino; 2022 UInt mode; 2023 NSegment seg; 2024 Bool needDiscard; 2025 2026 aspacem_assert(len > 0); 2027 aspacem_assert(VG_IS_PAGE_ALIGNED(a)); 2028 aspacem_assert(VG_IS_PAGE_ALIGNED(len)); 2029 aspacem_assert(VG_IS_PAGE_ALIGNED(offset)); 2030 2031 /* Discard is needed if any of the just-trashed range had T. */ 2032 needDiscard = any_Ts_in_range( a, len ); 2033 2034 init_nsegment( &seg ); 2035 seg.kind = (flags & VKI_MAP_ANONYMOUS) ? SkAnonC : SkFileC; 2036 seg.start = a; 2037 seg.end = a + len - 1; 2038 seg.hasR = toBool(prot & VKI_PROT_READ); 2039 seg.hasW = toBool(prot & VKI_PROT_WRITE); 2040 seg.hasX = toBool(prot & VKI_PROT_EXEC); 2041 if (!(flags & VKI_MAP_ANONYMOUS)) { 2042 // Nb: We ignore offset requests in anonymous mmaps (see bug #126722) 2043 seg.offset = offset; 2044 if (ML_(am_get_fd_d_i_m)(fd, &dev, &ino, &mode)) { 2045 seg.dev = dev; 2046 seg.ino = ino; 2047 seg.mode = mode; 2048 } 2049 if (ML_(am_resolve_filename)(fd, buf, VKI_PATH_MAX)) { 2050 seg.fnIdx = allocate_segname( buf ); 2051 } 2052 } 2053 add_segment( &seg ); 2054 AM_SANITY_CHECK; 2055 return needDiscard; 2056 } 2057 2058 /* Notifies aspacem that the client completed a shmat successfully. 2059 The segment array is updated accordingly. If the returned Bool is 2060 True, the caller should immediately discard translations from the 2061 specified address range. */ 2062 2063 Bool 2064 VG_(am_notify_client_shmat)( Addr a, SizeT len, UInt prot ) 2065 { 2066 NSegment seg; 2067 Bool needDiscard; 2068 2069 aspacem_assert(len > 0); 2070 aspacem_assert(VG_IS_PAGE_ALIGNED(a)); 2071 aspacem_assert(VG_IS_PAGE_ALIGNED(len)); 2072 2073 /* Discard is needed if any of the just-trashed range had T. */ 2074 needDiscard = any_Ts_in_range( a, len ); 2075 2076 init_nsegment( &seg ); 2077 seg.kind = SkShmC; 2078 seg.start = a; 2079 seg.end = a + len - 1; 2080 seg.offset = 0; 2081 seg.hasR = toBool(prot & VKI_PROT_READ); 2082 seg.hasW = toBool(prot & VKI_PROT_WRITE); 2083 seg.hasX = toBool(prot & VKI_PROT_EXEC); 2084 add_segment( &seg ); 2085 AM_SANITY_CHECK; 2086 return needDiscard; 2087 } 2088 2089 /* Notifies aspacem that an mprotect was completed successfully. The 2090 segment array is updated accordingly. Note, as with 2091 VG_(am_notify_munmap), it is not the job of this function to reject 2092 stupid mprotects, for example the client doing mprotect of 2093 non-client areas. Such requests should be intercepted earlier, by 2094 the syscall wrapper for mprotect. This function merely records 2095 whatever it is told. If the returned Bool is True, the caller 2096 should immediately discard translations from the specified address 2097 range. */ 2098 2099 Bool VG_(am_notify_mprotect)( Addr start, SizeT len, UInt prot ) 2100 { 2101 Int i, iLo, iHi; 2102 Bool newR, newW, newX, needDiscard; 2103 2104 aspacem_assert(VG_IS_PAGE_ALIGNED(start)); 2105 aspacem_assert(VG_IS_PAGE_ALIGNED(len)); 2106 2107 if (len == 0) 2108 return False; 2109 2110 newR = toBool(prot & VKI_PROT_READ); 2111 newW = toBool(prot & VKI_PROT_WRITE); 2112 newX = toBool(prot & VKI_PROT_EXEC); 2113 2114 /* Discard is needed if we're dumping X permission */ 2115 needDiscard = any_Ts_in_range( start, len ) && !newX; 2116 2117 split_nsegments_lo_and_hi( start, start+len-1, &iLo, &iHi ); 2118 2119 iLo = find_nsegment_idx(start); 2120 iHi = find_nsegment_idx(start + len - 1); 2121 2122 for (i = iLo; i <= iHi; i++) { 2123 /* Apply the permissions to all relevant segments. */ 2124 switch (nsegments[i].kind) { 2125 case SkAnonC: case SkAnonV: case SkFileC: case SkFileV: case SkShmC: 2126 nsegments[i].hasR = newR; 2127 nsegments[i].hasW = newW; 2128 nsegments[i].hasX = newX; 2129 aspacem_assert(sane_NSegment(&nsegments[i])); 2130 break; 2131 default: 2132 break; 2133 } 2134 } 2135 2136 /* Changing permissions could have made previously un-mergable 2137 segments mergeable. Therefore have to re-preen them. */ 2138 (void)preen_nsegments(); 2139 AM_SANITY_CHECK; 2140 return needDiscard; 2141 } 2142 2143 2144 /* Notifies aspacem that an munmap completed successfully. The 2145 segment array is updated accordingly. As with 2146 VG_(am_notify_munmap), we merely record the given info, and don't 2147 check it for sensibleness. If the returned Bool is True, the 2148 caller should immediately discard translations from the specified 2149 address range. */ 2150 2151 Bool VG_(am_notify_munmap)( Addr start, SizeT len ) 2152 { 2153 NSegment seg; 2154 Bool needDiscard; 2155 aspacem_assert(VG_IS_PAGE_ALIGNED(start)); 2156 aspacem_assert(VG_IS_PAGE_ALIGNED(len)); 2157 2158 if (len == 0) 2159 return False; 2160 2161 needDiscard = any_Ts_in_range( start, len ); 2162 2163 init_nsegment( &seg ); 2164 seg.start = start; 2165 seg.end = start + len - 1; 2166 2167 /* The segment becomes unused (free). Segments from above 2168 aspacem_maxAddr were originally SkResvn and so we make them so 2169 again. Note, this isn't really right when the segment straddles 2170 the aspacem_maxAddr boundary - then really it should be split in 2171 two, the lower part marked as SkFree and the upper part as 2172 SkResvn. Ah well. */ 2173 if (start > aspacem_maxAddr 2174 && /* check previous comparison is meaningful */ 2175 aspacem_maxAddr < Addr_MAX) 2176 seg.kind = SkResvn; 2177 else 2178 /* Ditto for segments from below aspacem_minAddr. */ 2179 if (seg.end < aspacem_minAddr && aspacem_minAddr > 0) 2180 seg.kind = SkResvn; 2181 else 2182 seg.kind = SkFree; 2183 2184 add_segment( &seg ); 2185 2186 /* Unmapping could create two adjacent free segments, so a preen is 2187 needed. add_segment() will do that, so no need to here. */ 2188 AM_SANITY_CHECK; 2189 return needDiscard; 2190 } 2191 2192 2193 /*-----------------------------------------------------------------*/ 2194 /*--- ---*/ 2195 /*--- Handling mappings which do not arise directly from the ---*/ 2196 /*--- simulation of the client. ---*/ 2197 /*--- ---*/ 2198 /*-----------------------------------------------------------------*/ 2199 2200 /* --- --- --- map, unmap, protect --- --- --- */ 2201 2202 /* Map a file at a fixed address for the client, and update the 2203 segment array accordingly. */ 2204 2205 SysRes VG_(am_mmap_file_fixed_client) 2206 ( Addr start, SizeT length, UInt prot, Int fd, Off64T offset ) 2207 { 2208 return VG_(am_mmap_named_file_fixed_client)(start, length, prot, fd, offset, NULL); 2209 } 2210 2211 SysRes VG_(am_mmap_named_file_fixed_client) 2212 ( Addr start, SizeT length, UInt prot, Int fd, Off64T offset, const HChar *name ) 2213 { 2214 SysRes sres; 2215 NSegment seg; 2216 Addr advised; 2217 Bool ok; 2218 MapRequest req; 2219 ULong dev, ino; 2220 UInt mode; 2221 HChar buf[VKI_PATH_MAX]; 2222 2223 /* Not allowable. */ 2224 if (length == 0 2225 || !VG_IS_PAGE_ALIGNED(start) 2226 || !VG_IS_PAGE_ALIGNED(offset)) 2227 return VG_(mk_SysRes_Error)( VKI_EINVAL ); 2228 2229 /* Ask for an advisory. If it's negative, fail immediately. */ 2230 req.rkind = MFixed; 2231 req.start = start; 2232 req.len = length; 2233 advised = VG_(am_get_advisory)( &req, True/*forClient*/, &ok ); 2234 if (!ok || advised != start) 2235 return VG_(mk_SysRes_Error)( VKI_EINVAL ); 2236 2237 /* We have been advised that the mapping is allowable at the 2238 specified address. So hand it off to the kernel, and propagate 2239 any resulting failure immediately. */ 2240 // DDD: #warning GrP fixme MAP_FIXED can clobber memory! 2241 sres = VG_(am_do_mmap_NO_NOTIFY)( 2242 start, length, prot, 2243 VKI_MAP_FIXED|VKI_MAP_PRIVATE, 2244 fd, offset 2245 ); 2246 if (sr_isError(sres)) 2247 return sres; 2248 2249 if (sr_Res(sres) != start) { 2250 /* I don't think this can happen. It means the kernel made a 2251 fixed map succeed but not at the requested location. Try to 2252 repair the damage, then return saying the mapping failed. */ 2253 (void)ML_(am_do_munmap_NO_NOTIFY)( sr_Res(sres), length ); 2254 return VG_(mk_SysRes_Error)( VKI_EINVAL ); 2255 } 2256 2257 /* Ok, the mapping succeeded. Now notify the interval map. */ 2258 init_nsegment( &seg ); 2259 seg.kind = SkFileC; 2260 seg.start = start; 2261 seg.end = seg.start + VG_PGROUNDUP(length) - 1; 2262 seg.offset = offset; 2263 seg.hasR = toBool(prot & VKI_PROT_READ); 2264 seg.hasW = toBool(prot & VKI_PROT_WRITE); 2265 seg.hasX = toBool(prot & VKI_PROT_EXEC); 2266 if (ML_(am_get_fd_d_i_m)(fd, &dev, &ino, &mode)) { 2267 seg.dev = dev; 2268 seg.ino = ino; 2269 seg.mode = mode; 2270 } 2271 if (name) { 2272 seg.fnIdx = allocate_segname( name ); 2273 } else if (ML_(am_resolve_filename)(fd, buf, VKI_PATH_MAX)) { 2274 seg.fnIdx = allocate_segname( buf ); 2275 } 2276 add_segment( &seg ); 2277 2278 AM_SANITY_CHECK; 2279 return sres; 2280 } 2281 2282 2283 /* Map anonymously at a fixed address for the client, and update 2284 the segment array accordingly. */ 2285 2286 SysRes VG_(am_mmap_anon_fixed_client) ( Addr start, SizeT length, UInt prot ) 2287 { 2288 SysRes sres; 2289 NSegment seg; 2290 Addr advised; 2291 Bool ok; 2292 MapRequest req; 2293 2294 /* Not allowable. */ 2295 if (length == 0 || !VG_IS_PAGE_ALIGNED(start)) 2296 return VG_(mk_SysRes_Error)( VKI_EINVAL ); 2297 2298 /* Ask for an advisory. If it's negative, fail immediately. */ 2299 req.rkind = MFixed; 2300 req.start = start; 2301 req.len = length; 2302 advised = VG_(am_get_advisory)( &req, True/*forClient*/, &ok ); 2303 if (!ok || advised != start) 2304 return VG_(mk_SysRes_Error)( VKI_EINVAL ); 2305 2306 /* We have been advised that the mapping is allowable at the 2307 specified address. So hand it off to the kernel, and propagate 2308 any resulting failure immediately. */ 2309 // DDD: #warning GrP fixme MAP_FIXED can clobber memory! 2310 sres = VG_(am_do_mmap_NO_NOTIFY)( 2311 start, length, prot, 2312 VKI_MAP_FIXED|VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, 2313 0, 0 2314 ); 2315 if (sr_isError(sres)) 2316 return sres; 2317 2318 if (sr_Res(sres) != start) { 2319 /* I don't think this can happen. It means the kernel made a 2320 fixed map succeed but not at the requested location. Try to 2321 repair the damage, then return saying the mapping failed. */ 2322 (void)ML_(am_do_munmap_NO_NOTIFY)( sr_Res(sres), length ); 2323 return VG_(mk_SysRes_Error)( VKI_EINVAL ); 2324 } 2325 2326 /* Ok, the mapping succeeded. Now notify the interval map. */ 2327 init_nsegment( &seg ); 2328 seg.kind = SkAnonC; 2329 seg.start = start; 2330 seg.end = seg.start + VG_PGROUNDUP(length) - 1; 2331 seg.hasR = toBool(prot & VKI_PROT_READ); 2332 seg.hasW = toBool(prot & VKI_PROT_WRITE); 2333 seg.hasX = toBool(prot & VKI_PROT_EXEC); 2334 add_segment( &seg ); 2335 2336 AM_SANITY_CHECK; 2337 return sres; 2338 } 2339 2340 2341 /* Map anonymously at an unconstrained address for the client, and 2342 update the segment array accordingly. */ 2343 2344 SysRes VG_(am_mmap_anon_float_client) ( SizeT length, Int prot ) 2345 { 2346 SysRes sres; 2347 NSegment seg; 2348 Addr advised; 2349 Bool ok; 2350 MapRequest req; 2351 2352 /* Not allowable. */ 2353 if (length == 0) 2354 return VG_(mk_SysRes_Error)( VKI_EINVAL ); 2355 2356 /* Ask for an advisory. If it's negative, fail immediately. */ 2357 req.rkind = MAny; 2358 req.start = 0; 2359 req.len = length; 2360 advised = VG_(am_get_advisory)( &req, True/*forClient*/, &ok ); 2361 if (!ok) 2362 return VG_(mk_SysRes_Error)( VKI_EINVAL ); 2363 2364 /* We have been advised that the mapping is allowable at the 2365 advised address. So hand it off to the kernel, and propagate 2366 any resulting failure immediately. */ 2367 // DDD: #warning GrP fixme MAP_FIXED can clobber memory! 2368 sres = VG_(am_do_mmap_NO_NOTIFY)( 2369 advised, length, prot, 2370 VKI_MAP_FIXED|VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, 2371 0, 0 2372 ); 2373 if (sr_isError(sres)) 2374 return sres; 2375 2376 if (sr_Res(sres) != advised) { 2377 /* I don't think this can happen. It means the kernel made a 2378 fixed map succeed but not at the requested location. Try to 2379 repair the damage, then return saying the mapping failed. */ 2380 (void)ML_(am_do_munmap_NO_NOTIFY)( sr_Res(sres), length ); 2381 return VG_(mk_SysRes_Error)( VKI_EINVAL ); 2382 } 2383 2384 /* Ok, the mapping succeeded. Now notify the interval map. */ 2385 init_nsegment( &seg ); 2386 seg.kind = SkAnonC; 2387 seg.start = advised; 2388 seg.end = seg.start + VG_PGROUNDUP(length) - 1; 2389 seg.hasR = toBool(prot & VKI_PROT_READ); 2390 seg.hasW = toBool(prot & VKI_PROT_WRITE); 2391 seg.hasX = toBool(prot & VKI_PROT_EXEC); 2392 add_segment( &seg ); 2393 2394 AM_SANITY_CHECK; 2395 return sres; 2396 } 2397 2398 2399 /* Similarly, acquire new address space for the client but with 2400 considerable restrictions on what can be done with it: (1) the 2401 actual protections may exceed those stated in 'prot', (2) the 2402 area's protections cannot be later changed using any form of 2403 mprotect, and (3) the area cannot be freed using any form of 2404 munmap. On Linux this behaves the same as 2405 VG_(am_mmap_anon_float_client). On AIX5 this *may* allocate memory 2406 by using sbrk, so as to make use of large pages on AIX. */ 2407 2408 SysRes VG_(am_sbrk_anon_float_client) ( SizeT length, Int prot ) 2409 { 2410 return VG_(am_mmap_anon_float_client) ( length, prot ); 2411 } 2412 2413 2414 /* Map anonymously at an unconstrained address for V, and update the 2415 segment array accordingly. This is fundamentally how V allocates 2416 itself more address space when needed. */ 2417 2418 SysRes VG_(am_mmap_anon_float_valgrind)( SizeT length ) 2419 { 2420 SysRes sres; 2421 NSegment seg; 2422 Addr advised; 2423 Bool ok; 2424 MapRequest req; 2425 2426 /* Not allowable. */ 2427 if (length == 0) 2428 return VG_(mk_SysRes_Error)( VKI_EINVAL ); 2429 2430 /* Ask for an advisory. If it's negative, fail immediately. */ 2431 req.rkind = MAny; 2432 req.start = 0; 2433 req.len = length; 2434 advised = VG_(am_get_advisory)( &req, False/*forClient*/, &ok ); 2435 if (!ok) 2436 return VG_(mk_SysRes_Error)( VKI_EINVAL ); 2437 2438 // On Darwin, for anonymous maps you can pass in a tag which is used by 2439 // programs like vmmap for statistical purposes. 2440 #ifndef VM_TAG_VALGRIND 2441 # define VM_TAG_VALGRIND 0 2442 #endif 2443 2444 /* We have been advised that the mapping is allowable at the 2445 specified address. So hand it off to the kernel, and propagate 2446 any resulting failure immediately. */ 2447 /* GrP fixme darwin: use advisory as a hint only, otherwise syscall in 2448 another thread can pre-empt our spot. [At one point on the DARWIN 2449 branch the VKI_MAP_FIXED was commented out; unclear if this is 2450 necessary or not given the second Darwin-only call that immediately 2451 follows if this one fails. --njn] */ 2452 sres = VG_(am_do_mmap_NO_NOTIFY)( 2453 advised, length, 2454 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC, 2455 VKI_MAP_FIXED|VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, 2456 VM_TAG_VALGRIND, 0 2457 ); 2458 #if defined(VGO_darwin) 2459 if (sr_isError(sres)) { 2460 /* try again, ignoring the advisory */ 2461 sres = VG_(am_do_mmap_NO_NOTIFY)( 2462 0, length, 2463 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC, 2464 /*VKI_MAP_FIXED|*/VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, 2465 VM_TAG_VALGRIND, 0 2466 ); 2467 } 2468 #endif 2469 if (sr_isError(sres)) 2470 return sres; 2471 2472 #if defined(VGO_linux) 2473 if (sr_Res(sres) != advised) { 2474 /* I don't think this can happen. It means the kernel made a 2475 fixed map succeed but not at the requested location. Try to 2476 repair the damage, then return saying the mapping failed. */ 2477 (void)ML_(am_do_munmap_NO_NOTIFY)( sr_Res(sres), length ); 2478 return VG_(mk_SysRes_Error)( VKI_EINVAL ); 2479 } 2480 #endif 2481 2482 /* Ok, the mapping succeeded. Now notify the interval map. */ 2483 init_nsegment( &seg ); 2484 seg.kind = SkAnonV; 2485 seg.start = sr_Res(sres); 2486 seg.end = seg.start + VG_PGROUNDUP(length) - 1; 2487 seg.hasR = True; 2488 seg.hasW = True; 2489 seg.hasX = True; 2490 add_segment( &seg ); 2491 2492 AM_SANITY_CHECK; 2493 return sres; 2494 } 2495 2496 /* Really just a wrapper around VG_(am_mmap_anon_float_valgrind). */ 2497 2498 void* VG_(am_shadow_alloc)(SizeT size) 2499 { 2500 SysRes sres = VG_(am_mmap_anon_float_valgrind)( size ); 2501 return sr_isError(sres) ? NULL : (void*)sr_Res(sres); 2502 } 2503 2504 /* Same comments apply as per VG_(am_sbrk_anon_float_client). On 2505 Linux this behaves the same as VG_(am_mmap_anon_float_valgrind). */ 2506 2507 SysRes VG_(am_sbrk_anon_float_valgrind)( SizeT cszB ) 2508 { 2509 return VG_(am_mmap_anon_float_valgrind)( cszB ); 2510 } 2511 2512 2513 /* Map a file at an unconstrained address for V, and update the 2514 segment array accordingly. Use the provided flags */ 2515 2516 static SysRes VG_(am_mmap_file_float_valgrind_flags) ( SizeT length, UInt prot, 2517 UInt flags, 2518 Int fd, Off64T offset ) 2519 { 2520 SysRes sres; 2521 NSegment seg; 2522 Addr advised; 2523 Bool ok; 2524 MapRequest req; 2525 ULong dev, ino; 2526 UInt mode; 2527 HChar buf[VKI_PATH_MAX]; 2528 2529 /* Not allowable. */ 2530 if (length == 0 || !VG_IS_PAGE_ALIGNED(offset)) 2531 return VG_(mk_SysRes_Error)( VKI_EINVAL ); 2532 2533 /* Ask for an advisory. If it's negative, fail immediately. */ 2534 req.rkind = MAny; 2535 req.start = 0; 2536 #if defined(VGA_arm) || defined(VGA_mips32) 2537 aspacem_assert(VKI_SHMLBA >= VKI_PAGE_SIZE); 2538 #else 2539 aspacem_assert(VKI_SHMLBA == VKI_PAGE_SIZE); 2540 #endif 2541 if ((VKI_SHMLBA > VKI_PAGE_SIZE) && (VKI_MAP_SHARED & flags)) { 2542 /* arm-linux only. See ML_(generic_PRE_sys_shmat) and bug 290974 */ 2543 req.len = length + VKI_SHMLBA - VKI_PAGE_SIZE; 2544 } else { 2545 req.len = length; 2546 } 2547 advised = VG_(am_get_advisory)( &req, False/*forClient*/, &ok ); 2548 if (!ok) 2549 return VG_(mk_SysRes_Error)( VKI_EINVAL ); 2550 if ((VKI_SHMLBA > VKI_PAGE_SIZE) && (VKI_MAP_SHARED & flags)) 2551 advised = VG_ROUNDUP(advised, VKI_SHMLBA); 2552 2553 /* We have been advised that the mapping is allowable at the 2554 specified address. So hand it off to the kernel, and propagate 2555 any resulting failure immediately. */ 2556 sres = VG_(am_do_mmap_NO_NOTIFY)( 2557 advised, length, prot, 2558 flags, 2559 fd, offset 2560 ); 2561 if (sr_isError(sres)) 2562 return sres; 2563 2564 if (sr_Res(sres) != advised) { 2565 /* I don't think this can happen. It means the kernel made a 2566 fixed map succeed but not at the requested location. Try to 2567 repair the damage, then return saying the mapping failed. */ 2568 (void)ML_(am_do_munmap_NO_NOTIFY)( sr_Res(sres), length ); 2569 return VG_(mk_SysRes_Error)( VKI_EINVAL ); 2570 } 2571 2572 /* Ok, the mapping succeeded. Now notify the interval map. */ 2573 init_nsegment( &seg ); 2574 seg.kind = SkFileV; 2575 seg.start = sr_Res(sres); 2576 seg.end = seg.start + VG_PGROUNDUP(length) - 1; 2577 seg.offset = offset; 2578 seg.hasR = toBool(prot & VKI_PROT_READ); 2579 seg.hasW = toBool(prot & VKI_PROT_WRITE); 2580 seg.hasX = toBool(prot & VKI_PROT_EXEC); 2581 if (ML_(am_get_fd_d_i_m)(fd, &dev, &ino, &mode)) { 2582 seg.dev = dev; 2583 seg.ino = ino; 2584 seg.mode = mode; 2585 } 2586 if (ML_(am_resolve_filename)(fd, buf, VKI_PATH_MAX)) { 2587 seg.fnIdx = allocate_segname( buf ); 2588 } 2589 add_segment( &seg ); 2590 2591 AM_SANITY_CHECK; 2592 return sres; 2593 } 2594 /* Map privately a file at an unconstrained address for V, and update the 2595 segment array accordingly. This is used by V for transiently 2596 mapping in object files to read their debug info. */ 2597 2598 SysRes VG_(am_mmap_file_float_valgrind) ( SizeT length, UInt prot, 2599 Int fd, Off64T offset ) 2600 { 2601 return VG_(am_mmap_file_float_valgrind_flags) (length, prot, 2602 VKI_MAP_FIXED|VKI_MAP_PRIVATE, 2603 fd, offset ); 2604 } 2605 2606 SysRes VG_(am_shared_mmap_file_float_valgrind) 2607 ( SizeT length, UInt prot, Int fd, Off64T offset ) 2608 { 2609 return VG_(am_mmap_file_float_valgrind_flags) (length, prot, 2610 VKI_MAP_FIXED|VKI_MAP_SHARED, 2611 fd, offset ); 2612 } 2613 2614 /* --- --- munmap helper --- --- */ 2615 2616 static 2617 SysRes am_munmap_both_wrk ( /*OUT*/Bool* need_discard, 2618 Addr start, SizeT len, Bool forClient ) 2619 { 2620 Bool d; 2621 SysRes sres; 2622 2623 if (!VG_IS_PAGE_ALIGNED(start)) 2624 goto eINVAL; 2625 2626 if (len == 0) { 2627 *need_discard = False; 2628 return VG_(mk_SysRes_Success)( 0 ); 2629 } 2630 2631 if (start + len < len) 2632 goto eINVAL; 2633 2634 len = VG_PGROUNDUP(len); 2635 aspacem_assert(VG_IS_PAGE_ALIGNED(start)); 2636 aspacem_assert(VG_IS_PAGE_ALIGNED(len)); 2637 2638 if (forClient) { 2639 if (!VG_(am_is_valid_for_client_or_free_or_resvn) 2640 ( start, len, VKI_PROT_NONE )) 2641 goto eINVAL; 2642 } else { 2643 if (!is_valid_for_valgrind( start, len )) 2644 goto eINVAL; 2645 } 2646 2647 d = any_Ts_in_range( start, len ); 2648 2649 sres = ML_(am_do_munmap_NO_NOTIFY)( start, len ); 2650 if (sr_isError(sres)) 2651 return sres; 2652 2653 VG_(am_notify_munmap)( start, len ); 2654 AM_SANITY_CHECK; 2655 *need_discard = d; 2656 return sres; 2657 2658 eINVAL: 2659 return VG_(mk_SysRes_Error)( VKI_EINVAL ); 2660 } 2661 2662 /* Unmap the given address range and update the segment array 2663 accordingly. This fails if the range isn't valid for the client. 2664 If *need_discard is True after a successful return, the caller 2665 should immediately discard translations from the specified address 2666 range. */ 2667 2668 SysRes VG_(am_munmap_client)( /*OUT*/Bool* need_discard, 2669 Addr start, SizeT len ) 2670 { 2671 return am_munmap_both_wrk( need_discard, start, len, True/*client*/ ); 2672 } 2673 2674 /* Unmap the given address range and update the segment array 2675 accordingly. This fails if the range isn't valid for valgrind. */ 2676 2677 SysRes VG_(am_munmap_valgrind)( Addr start, SizeT len ) 2678 { 2679 Bool need_discard; 2680 SysRes r = am_munmap_both_wrk( &need_discard, 2681 start, len, False/*valgrind*/ ); 2682 /* If this assertion fails, it means we allowed translations to be 2683 made from a V-owned section. Which shouldn't happen. */ 2684 if (!sr_isError(r)) 2685 aspacem_assert(!need_discard); 2686 return r; 2687 } 2688 2689 /* Let (start,len) denote an area within a single Valgrind-owned 2690 segment (anon or file). Change the ownership of [start, start+len) 2691 to the client instead. Fails if (start,len) does not denote a 2692 suitable segment. */ 2693 2694 Bool VG_(am_change_ownership_v_to_c)( Addr start, SizeT len ) 2695 { 2696 Int i, iLo, iHi; 2697 2698 if (len == 0) 2699 return True; 2700 if (start + len < start) 2701 return False; 2702 if (!VG_IS_PAGE_ALIGNED(start) || !VG_IS_PAGE_ALIGNED(len)) 2703 return False; 2704 2705 i = find_nsegment_idx(start); 2706 if (nsegments[i].kind != SkFileV && nsegments[i].kind != SkAnonV) 2707 return False; 2708 if (start+len-1 > nsegments[i].end) 2709 return False; 2710 2711 aspacem_assert(start >= nsegments[i].start); 2712 aspacem_assert(start+len-1 <= nsegments[i].end); 2713 2714 /* This scheme is like how mprotect works: split the to-be-changed 2715 range into its own segment(s), then mess with them (it). There 2716 should be only one. */ 2717 split_nsegments_lo_and_hi( start, start+len-1, &iLo, &iHi ); 2718 aspacem_assert(iLo == iHi); 2719 switch (nsegments[iLo].kind) { 2720 case SkFileV: nsegments[iLo].kind = SkFileC; break; 2721 case SkAnonV: nsegments[iLo].kind = SkAnonC; break; 2722 default: aspacem_assert(0); /* can't happen - guarded above */ 2723 } 2724 2725 preen_nsegments(); 2726 return True; 2727 } 2728 2729 /* 'seg' must be NULL or have been obtained from 2730 VG_(am_find_nsegment), and still valid. If non-NULL, and if it 2731 denotes a SkAnonC (anonymous client mapping) area, set the .isCH 2732 (is-client-heap) flag for that area. Otherwise do nothing. 2733 (Bizarre interface so that the same code works for both Linux and 2734 AIX and does not impose inefficiencies on the Linux version.) */ 2735 void VG_(am_set_segment_isCH_if_SkAnonC)( NSegment* seg ) 2736 { 2737 Int i = segAddr_to_index( seg ); 2738 aspacem_assert(i >= 0 && i < nsegments_used); 2739 if (nsegments[i].kind == SkAnonC) { 2740 nsegments[i].isCH = True; 2741 } else { 2742 aspacem_assert(nsegments[i].isCH == False); 2743 } 2744 } 2745 2746 /* Same idea as VG_(am_set_segment_isCH_if_SkAnonC), except set the 2747 segment's hasT bit (has-cached-code) if this is SkFileC or SkAnonC 2748 segment. */ 2749 void VG_(am_set_segment_hasT_if_SkFileC_or_SkAnonC)( NSegment* seg ) 2750 { 2751 Int i = segAddr_to_index( seg ); 2752 aspacem_assert(i >= 0 && i < nsegments_used); 2753 if (nsegments[i].kind == SkAnonC || nsegments[i].kind == SkFileC) { 2754 nsegments[i].hasT = True; 2755 } 2756 } 2757 2758 2759 /* --- --- --- reservations --- --- --- */ 2760 2761 /* Create a reservation from START .. START+LENGTH-1, with the given 2762 ShrinkMode. When checking whether the reservation can be created, 2763 also ensure that at least abs(EXTRA) extra free bytes will remain 2764 above (> 0) or below (< 0) the reservation. 2765 2766 The reservation will only be created if it, plus the extra-zone, 2767 falls entirely within a single free segment. The returned Bool 2768 indicates whether the creation succeeded. */ 2769 2770 Bool VG_(am_create_reservation) ( Addr start, SizeT length, 2771 ShrinkMode smode, SSizeT extra ) 2772 { 2773 Int startI, endI; 2774 NSegment seg; 2775 2776 /* start and end, not taking into account the extra space. */ 2777 Addr start1 = start; 2778 Addr end1 = start + length - 1; 2779 2780 /* start and end, taking into account the extra space. */ 2781 Addr start2 = start1; 2782 Addr end2 = end1; 2783 2784 if (extra < 0) start2 += extra; // this moves it down :-) 2785 if (extra > 0) end2 += extra; 2786 2787 aspacem_assert(VG_IS_PAGE_ALIGNED(start)); 2788 aspacem_assert(VG_IS_PAGE_ALIGNED(start+length)); 2789 aspacem_assert(VG_IS_PAGE_ALIGNED(start2)); 2790 aspacem_assert(VG_IS_PAGE_ALIGNED(end2+1)); 2791 2792 startI = find_nsegment_idx( start2 ); 2793 endI = find_nsegment_idx( end2 ); 2794 2795 /* If the start and end points don't fall within the same (free) 2796 segment, we're hosed. This does rely on the assumption that all 2797 mergeable adjacent segments can be merged, but add_segment() 2798 should ensure that. */ 2799 if (startI != endI) 2800 return False; 2801 2802 if (nsegments[startI].kind != SkFree) 2803 return False; 2804 2805 /* Looks good - make the reservation. */ 2806 aspacem_assert(nsegments[startI].start <= start2); 2807 aspacem_assert(end2 <= nsegments[startI].end); 2808 2809 init_nsegment( &seg ); 2810 seg.kind = SkResvn; 2811 seg.start = start1; /* NB: extra space is not included in the 2812 reservation. */ 2813 seg.end = end1; 2814 seg.smode = smode; 2815 add_segment( &seg ); 2816 2817 AM_SANITY_CHECK; 2818 return True; 2819 } 2820 2821 2822 /* Let SEG be an anonymous client mapping. This fn extends the 2823 mapping by DELTA bytes, taking the space from a reservation section 2824 which must be adjacent. If DELTA is positive, the segment is 2825 extended forwards in the address space, and the reservation must be 2826 the next one along. If DELTA is negative, the segment is extended 2827 backwards in the address space and the reservation must be the 2828 previous one. DELTA must be page aligned. abs(DELTA) must not 2829 exceed the size of the reservation segment minus one page, that is, 2830 the reservation segment after the operation must be at least one 2831 page long. */ 2832 2833 Bool VG_(am_extend_into_adjacent_reservation_client) ( NSegment* seg, 2834 SSizeT delta ) 2835 { 2836 Int segA, segR; 2837 UInt prot; 2838 SysRes sres; 2839 2840 /* Find the segment array index for SEG. If the assertion fails it 2841 probably means you passed in a bogus SEG. */ 2842 segA = segAddr_to_index( seg ); 2843 aspacem_assert(segA >= 0 && segA < nsegments_used); 2844 2845 if (nsegments[segA].kind != SkAnonC) 2846 return False; 2847 2848 if (delta == 0) 2849 return True; 2850 2851 prot = (nsegments[segA].hasR ? VKI_PROT_READ : 0) 2852 | (nsegments[segA].hasW ? VKI_PROT_WRITE : 0) 2853 | (nsegments[segA].hasX ? VKI_PROT_EXEC : 0); 2854 2855 aspacem_assert(VG_IS_PAGE_ALIGNED(delta<0 ? -delta : delta)); 2856 2857 if (delta > 0) { 2858 2859 /* Extending the segment forwards. */ 2860 segR = segA+1; 2861 if (segR >= nsegments_used 2862 || nsegments[segR].kind != SkResvn 2863 || nsegments[segR].smode != SmLower 2864 || nsegments[segR].start != nsegments[segA].end + 1 2865 || delta + VKI_PAGE_SIZE 2866 > (nsegments[segR].end - nsegments[segR].start + 1)) 2867 return False; 2868 2869 /* Extend the kernel's mapping. */ 2870 // DDD: #warning GrP fixme MAP_FIXED can clobber memory! 2871 sres = VG_(am_do_mmap_NO_NOTIFY)( 2872 nsegments[segR].start, delta, 2873 prot, 2874 VKI_MAP_FIXED|VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, 2875 0, 0 2876 ); 2877 if (sr_isError(sres)) 2878 return False; /* kernel bug if this happens? */ 2879 if (sr_Res(sres) != nsegments[segR].start) { 2880 /* kernel bug if this happens? */ 2881 (void)ML_(am_do_munmap_NO_NOTIFY)( sr_Res(sres), delta ); 2882 return False; 2883 } 2884 2885 /* Ok, success with the kernel. Update our structures. */ 2886 nsegments[segR].start += delta; 2887 nsegments[segA].end += delta; 2888 aspacem_assert(nsegments[segR].start <= nsegments[segR].end); 2889 2890 } else { 2891 2892 /* Extending the segment backwards. */ 2893 delta = -delta; 2894 aspacem_assert(delta > 0); 2895 2896 segR = segA-1; 2897 if (segR < 0 2898 || nsegments[segR].kind != SkResvn 2899 || nsegments[segR].smode != SmUpper 2900 || nsegments[segR].end + 1 != nsegments[segA].start 2901 || delta + VKI_PAGE_SIZE 2902 > (nsegments[segR].end - nsegments[segR].start + 1)) 2903 return False; 2904 2905 /* Extend the kernel's mapping. */ 2906 // DDD: #warning GrP fixme MAP_FIXED can clobber memory! 2907 sres = VG_(am_do_mmap_NO_NOTIFY)( 2908 nsegments[segA].start-delta, delta, 2909 prot, 2910 VKI_MAP_FIXED|VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS, 2911 0, 0 2912 ); 2913 if (sr_isError(sres)) 2914 return False; /* kernel bug if this happens? */ 2915 if (sr_Res(sres) != nsegments[segA].start-delta) { 2916 /* kernel bug if this happens? */ 2917 (void)ML_(am_do_munmap_NO_NOTIFY)( sr_Res(sres), delta ); 2918 return False; 2919 } 2920 2921 /* Ok, success with the kernel. Update our structures. */ 2922 nsegments[segR].end -= delta; 2923 nsegments[segA].start -= delta; 2924 aspacem_assert(nsegments[segR].start <= nsegments[segR].end); 2925 2926 } 2927 2928 AM_SANITY_CHECK; 2929 return True; 2930 } 2931 2932 2933 /* --- --- --- resizing/move a mapping --- --- --- */ 2934 2935 #if HAVE_MREMAP 2936 2937 /* Let SEG be a client mapping (anonymous or file). This fn extends 2938 the mapping forwards only by DELTA bytes, and trashes whatever was 2939 in the new area. Fails if SEG is not a single client mapping or if 2940 the new area is not accessible to the client. Fails if DELTA is 2941 not page aligned. *seg is invalid after a successful return. If 2942 *need_discard is True after a successful return, the caller should 2943 immediately discard translations from the new area. */ 2944 2945 Bool VG_(am_extend_map_client)( /*OUT*/Bool* need_discard, 2946 NSegment* seg, SizeT delta ) 2947 { 2948 Addr xStart; 2949 SysRes sres; 2950 NSegment seg_copy = *seg; 2951 SizeT seg_old_len = seg->end + 1 - seg->start; 2952 2953 if (0) 2954 VG_(am_show_nsegments)(0, "VG_(am_extend_map_client) BEFORE"); 2955 2956 if (seg->kind != SkFileC && seg->kind != SkAnonC) 2957 return False; 2958 2959 if (delta == 0 || !VG_IS_PAGE_ALIGNED(delta)) 2960 return False; 2961 2962 xStart = seg->end+1; 2963 if (xStart + delta < delta) 2964 return False; 2965 2966 if (!VG_(am_is_valid_for_client_or_free_or_resvn)( xStart, delta, 2967 VKI_PROT_NONE )) 2968 return False; 2969 2970 AM_SANITY_CHECK; 2971 sres = ML_(am_do_extend_mapping_NO_NOTIFY)( seg->start, 2972 seg_old_len, 2973 seg_old_len + delta ); 2974 if (sr_isError(sres)) { 2975 AM_SANITY_CHECK; 2976 return False; 2977 } else { 2978 /* the area must not have moved */ 2979 aspacem_assert(sr_Res(sres) == seg->start); 2980 } 2981 2982 *need_discard = any_Ts_in_range( seg_copy.end+1, delta ); 2983 2984 seg_copy.end += delta; 2985 add_segment( &seg_copy ); 2986 2987 if (0) 2988 VG_(am_show_nsegments)(0, "VG_(am_extend_map_client) AFTER"); 2989 2990 AM_SANITY_CHECK; 2991 return True; 2992 } 2993 2994 2995 /* Remap the old address range to the new address range. Fails if any 2996 parameter is not page aligned, if the either size is zero, if any 2997 wraparound is implied, if the old address range does not fall 2998 entirely within a single segment, if the new address range overlaps 2999 with the old one, or if the old address range is not a valid client 3000 mapping. If *need_discard is True after a successful return, the 3001 caller should immediately discard translations from both specified 3002 address ranges. */ 3003 3004 Bool VG_(am_relocate_nooverlap_client)( /*OUT*/Bool* need_discard, 3005 Addr old_addr, SizeT old_len, 3006 Addr new_addr, SizeT new_len ) 3007 { 3008 Int iLo, iHi; 3009 SysRes sres; 3010 NSegment seg; 3011 3012 if (old_len == 0 || new_len == 0) 3013 return False; 3014 3015 if (!VG_IS_PAGE_ALIGNED(old_addr) || !VG_IS_PAGE_ALIGNED(old_len) 3016 || !VG_IS_PAGE_ALIGNED(new_addr) || !VG_IS_PAGE_ALIGNED(new_len)) 3017 return False; 3018 3019 if (old_addr + old_len < old_addr 3020 || new_addr + new_len < new_addr) 3021 return False; 3022 3023 if (old_addr + old_len - 1 < new_addr 3024 || new_addr + new_len - 1 < old_addr) { 3025 /* no overlap */ 3026 } else 3027 return False; 3028 3029 iLo = find_nsegment_idx( old_addr ); 3030 iHi = find_nsegment_idx( old_addr + old_len - 1 ); 3031 if (iLo != iHi) 3032 return False; 3033 3034 if (nsegments[iLo].kind != SkFileC && nsegments[iLo].kind != SkAnonC) 3035 return False; 3036 3037 sres = ML_(am_do_relocate_nooverlap_mapping_NO_NOTIFY) 3038 ( old_addr, old_len, new_addr, new_len ); 3039 if (sr_isError(sres)) { 3040 AM_SANITY_CHECK; 3041 return False; 3042 } else { 3043 aspacem_assert(sr_Res(sres) == new_addr); 3044 } 3045 3046 *need_discard = any_Ts_in_range( old_addr, old_len ) 3047 || any_Ts_in_range( new_addr, new_len ); 3048 3049 seg = nsegments[iLo]; 3050 3051 /* Mark the new area based on the old seg. */ 3052 if (seg.kind == SkFileC) { 3053 seg.offset += ((ULong)old_addr) - ((ULong)seg.start); 3054 } else { 3055 aspacem_assert(seg.kind == SkAnonC); 3056 aspacem_assert(seg.offset == 0); 3057 } 3058 seg.start = new_addr; 3059 seg.end = new_addr + new_len - 1; 3060 add_segment( &seg ); 3061 3062 /* Create a free hole in the old location. */ 3063 init_nsegment( &seg ); 3064 seg.start = old_addr; 3065 seg.end = old_addr + old_len - 1; 3066 /* See comments in VG_(am_notify_munmap) about this SkResvn vs 3067 SkFree thing. */ 3068 if (old_addr > aspacem_maxAddr 3069 && /* check previous comparison is meaningful */ 3070 aspacem_maxAddr < Addr_MAX) 3071 seg.kind = SkResvn; 3072 else 3073 seg.kind = SkFree; 3074 3075 add_segment( &seg ); 3076 3077 AM_SANITY_CHECK; 3078 return True; 3079 } 3080 3081 #endif // HAVE_MREMAP 3082 3083 3084 #if defined(VGO_linux) 3085 3086 /*-----------------------------------------------------------------*/ 3087 /*--- ---*/ 3088 /*--- A simple parser for /proc/self/maps on Linux 2.4.X/2.6.X. ---*/ 3089 /*--- Almost completely independent of the stuff above. The ---*/ 3090 /*--- only function it 'exports' to the code above this comment ---*/ 3091 /*--- is parse_procselfmaps. ---*/ 3092 /*--- ---*/ 3093 /*-----------------------------------------------------------------*/ 3094 3095 /*------BEGIN-procmaps-parser-for-Linux--------------------------*/ 3096 3097 /* Size of a smallish table used to read /proc/self/map entries. */ 3098 #define M_PROCMAP_BUF 100000 3099 3100 /* static ... to keep it out of the stack frame. */ 3101 static Char procmap_buf[M_PROCMAP_BUF]; 3102 3103 /* Records length of /proc/self/maps read into procmap_buf. */ 3104 static Int buf_n_tot; 3105 3106 /* Helper fns. */ 3107 3108 static Int hexdigit ( Char c ) 3109 { 3110 if (c >= '0' && c <= '9') return (Int)(c - '0'); 3111 if (c >= 'a' && c <= 'f') return 10 + (Int)(c - 'a'); 3112 if (c >= 'A' && c <= 'F') return 10 + (Int)(c - 'A'); 3113 return -1; 3114 } 3115 3116 static Int decdigit ( Char c ) 3117 { 3118 if (c >= '0' && c <= '9') return (Int)(c - '0'); 3119 return -1; 3120 } 3121 3122 static Int readchar ( const Char* buf, Char* ch ) 3123 { 3124 if (*buf == 0) return 0; 3125 *ch = *buf; 3126 return 1; 3127 } 3128 3129 static Int readhex ( const Char* buf, UWord* val ) 3130 { 3131 /* Read a word-sized hex number. */ 3132 Int n = 0; 3133 *val = 0; 3134 while (hexdigit(*buf) >= 0) { 3135 *val = (*val << 4) + hexdigit(*buf); 3136 n++; buf++; 3137 } 3138 return n; 3139 } 3140 3141 static Int readhex64 ( const Char* buf, ULong* val ) 3142 { 3143 /* Read a potentially 64-bit hex number. */ 3144 Int n = 0; 3145 *val = 0; 3146 while (hexdigit(*buf) >= 0) { 3147 *val = (*val << 4) + hexdigit(*buf); 3148 n++; buf++; 3149 } 3150 return n; 3151 } 3152 3153 static Int readdec64 ( const Char* buf, ULong* val ) 3154 { 3155 Int n = 0; 3156 *val = 0; 3157 while (decdigit(*buf) >= 0) { 3158 *val = (*val * 10) + decdigit(*buf); 3159 n++; buf++; 3160 } 3161 return n; 3162 } 3163 3164 3165 /* Get the contents of /proc/self/maps into a static buffer. If 3166 there's a syntax error, it won't fit, or other failure, just 3167 abort. */ 3168 3169 static void read_procselfmaps_into_buf ( void ) 3170 { 3171 Int n_chunk; 3172 SysRes fd; 3173 3174 /* Read the initial memory mapping from the /proc filesystem. */ 3175 fd = ML_(am_open)( "/proc/self/maps", VKI_O_RDONLY, 0 ); 3176 if (sr_isError(fd)) 3177 ML_(am_barf)("can't open /proc/self/maps"); 3178 3179 buf_n_tot = 0; 3180 do { 3181 n_chunk = ML_(am_read)( sr_Res(fd), &procmap_buf[buf_n_tot], 3182 M_PROCMAP_BUF - buf_n_tot ); 3183 if (n_chunk >= 0) 3184 buf_n_tot += n_chunk; 3185 } while ( n_chunk > 0 && buf_n_tot < M_PROCMAP_BUF ); 3186 3187 ML_(am_close)(sr_Res(fd)); 3188 3189 if (buf_n_tot >= M_PROCMAP_BUF-5) 3190 ML_(am_barf_toolow)("M_PROCMAP_BUF"); 3191 if (buf_n_tot == 0) 3192 ML_(am_barf)("I/O error on /proc/self/maps"); 3193 3194 procmap_buf[buf_n_tot] = 0; 3195 } 3196 3197 /* Parse /proc/self/maps. For each map entry, call 3198 record_mapping, passing it, in this order: 3199 3200 start address in memory 3201 length 3202 page protections (using the VKI_PROT_* flags) 3203 mapped file device and inode 3204 offset in file, or zero if no file 3205 filename, zero terminated, or NULL if no file 3206 3207 So the sig of the called fn might be 3208 3209 void (*record_mapping)( Addr start, SizeT size, UInt prot, 3210 UInt dev, UInt info, 3211 ULong foffset, UChar* filename ) 3212 3213 Note that the supplied filename is transiently stored; record_mapping 3214 should make a copy if it wants to keep it. 3215 3216 Nb: it is important that this function does not alter the contents of 3217 procmap_buf! 3218 */ 3219 static void parse_procselfmaps ( 3220 void (*record_mapping)( Addr addr, SizeT len, UInt prot, 3221 ULong dev, ULong ino, Off64T offset, 3222 const UChar* filename ), 3223 void (*record_gap)( Addr addr, SizeT len ) 3224 ) 3225 { 3226 Int i, j, i_eol; 3227 Addr start, endPlusOne, gapStart; 3228 UChar* filename; 3229 UChar rr, ww, xx, pp, ch, tmp; 3230 UInt prot; 3231 UWord maj, min; 3232 ULong foffset, dev, ino; 3233 3234 foffset = ino = 0; /* keep gcc-4.1.0 happy */ 3235 3236 read_procselfmaps_into_buf(); 3237 3238 aspacem_assert('\0' != procmap_buf[0] && 0 != buf_n_tot); 3239 3240 if (0) 3241 VG_(debugLog)(0, "procselfmaps", "raw:\n%s\n", procmap_buf); 3242 3243 /* Ok, it's safely aboard. Parse the entries. */ 3244 i = 0; 3245 gapStart = Addr_MIN; 3246 while (True) { 3247 if (i >= buf_n_tot) break; 3248 3249 /* Read (without fscanf :) the pattern %16x-%16x %c%c%c%c %16x %2x:%2x %d */ 3250 j = readhex(&procmap_buf[i], &start); 3251 if (j > 0) i += j; else goto syntaxerror; 3252 j = readchar(&procmap_buf[i], &ch); 3253 if (j == 1 && ch == '-') i += j; else goto syntaxerror; 3254 j = readhex(&procmap_buf[i], &endPlusOne); 3255 if (j > 0) i += j; else goto syntaxerror; 3256 3257 j = readchar(&procmap_buf[i], &ch); 3258 if (j == 1 && ch == ' ') i += j; else goto syntaxerror; 3259 3260 j = readchar(&procmap_buf[i], &rr); 3261 if (j == 1 && (rr == 'r' || rr == '-')) i += j; else goto syntaxerror; 3262 j = readchar(&procmap_buf[i], &ww); 3263 if (j == 1 && (ww == 'w' || ww == '-')) i += j; else goto syntaxerror; 3264 j = readchar(&procmap_buf[i], &xx); 3265 if (j == 1 && (xx == 'x' || xx == '-')) i += j; else goto syntaxerror; 3266 /* This field is the shared/private flag */ 3267 j = readchar(&procmap_buf[i], &pp); 3268 if (j == 1 && (pp == 'p' || pp == '-' || pp == 's')) 3269 i += j; else goto syntaxerror; 3270 3271 j = readchar(&procmap_buf[i], &ch); 3272 if (j == 1 && ch == ' ') i += j; else goto syntaxerror; 3273 3274 j = readhex64(&procmap_buf[i], &foffset); 3275 if (j > 0) i += j; else goto syntaxerror; 3276 3277 j = readchar(&procmap_buf[i], &ch); 3278 if (j == 1 && ch == ' ') i += j; else goto syntaxerror; 3279 3280 j = readhex(&procmap_buf[i], &maj); 3281 if (j > 0) i += j; else goto syntaxerror; 3282 j = readchar(&procmap_buf[i], &ch); 3283 if (j == 1 && ch == ':') i += j; else goto syntaxerror; 3284 j = readhex(&procmap_buf[i], &min); 3285 if (j > 0) i += j; else goto syntaxerror; 3286 3287 j = readchar(&procmap_buf[i], &ch); 3288 if (j == 1 && ch == ' ') i += j; else goto syntaxerror; 3289 3290 j = readdec64(&procmap_buf[i], &ino); 3291 if (j > 0) i += j; else goto syntaxerror; 3292 3293 goto read_line_ok; 3294 3295 syntaxerror: 3296 VG_(debugLog)(0, "Valgrind:", 3297 "FATAL: syntax error reading /proc/self/maps\n"); 3298 { Int k, m; 3299 HChar buf50[51]; 3300 m = 0; 3301 buf50[m] = 0; 3302 k = i - 50; 3303 if (k < 0) k = 0; 3304 for (; k <= i; k++) { 3305 buf50[m] = procmap_buf[k]; 3306 buf50[m+1] = 0; 3307 if (m < 50-1) m++; 3308 } 3309 VG_(debugLog)(0, "procselfmaps", "Last 50 chars: '%s'\n", buf50); 3310 } 3311 ML_(am_exit)(1); 3312 3313 read_line_ok: 3314 3315 aspacem_assert(i < buf_n_tot); 3316 3317 /* Try and find the name of the file mapped to this segment, if 3318 it exists. Note that file names can contain spaces. */ 3319 3320 // Move i to the next non-space char, which should be either a '/', 3321 // a '[', or a newline. 3322 while (procmap_buf[i] == ' ') i++; 3323 3324 // Move i_eol to the end of the line. 3325 i_eol = i; 3326 while (procmap_buf[i_eol] != '\n') i_eol++; 3327 3328 // If there's a filename... 3329 if (procmap_buf[i] == '/') { 3330 /* Minor hack: put a '\0' at the filename end for the call to 3331 'record_mapping', then restore the old char with 'tmp'. */ 3332 filename = &procmap_buf[i]; 3333 tmp = filename[i_eol - i]; 3334 filename[i_eol - i] = '\0'; 3335 } else { 3336 tmp = 0; 3337 filename = NULL; 3338 foffset = 0; 3339 } 3340 3341 prot = 0; 3342 if (rr == 'r') prot |= VKI_PROT_READ; 3343 if (ww == 'w') prot |= VKI_PROT_WRITE; 3344 if (xx == 'x') prot |= VKI_PROT_EXEC; 3345 3346 /* Linux has two ways to encode a device number when it 3347 is exposed to user space (via fstat etc). The old way 3348 is the traditional unix scheme that produces a 16 bit 3349 device number with the top 8 being the major number and 3350 the bottom 8 the minor number. 3351 3352 The new scheme allows for a 12 bit major number and 3353 a 20 bit minor number by using a 32 bit device number 3354 and putting the top 12 bits of the minor number into 3355 the top 12 bits of the device number thus leaving an 3356 extra 4 bits for the major number. 3357 3358 If the minor and major number are both single byte 3359 values then both schemes give the same result so we 3360 use the new scheme here in case either number is 3361 outside the 0-255 range and then use fstat64 when 3362 available (or fstat on 64 bit systems) so that we 3363 should always have a new style device number and 3364 everything should match. */ 3365 dev = (min & 0xff) | (maj << 8) | ((min & ~0xff) << 12); 3366 3367 if (record_gap && gapStart < start) 3368 (*record_gap) ( gapStart, start-gapStart ); 3369 3370 if (record_mapping && start < endPlusOne) 3371 (*record_mapping) ( start, endPlusOne-start, 3372 prot, dev, ino, 3373 foffset, filename ); 3374 3375 if ('\0' != tmp) { 3376 filename[i_eol - i] = tmp; 3377 } 3378 3379 i = i_eol + 1; 3380 gapStart = endPlusOne; 3381 } 3382 3383 # if defined(VGP_arm_linux) 3384 /* ARM puts code at the end of memory that contains processor 3385 specific stuff (cmpxchg, getting the thread local storage, etc.) 3386 This isn't specified in /proc/self/maps, so do it here. This 3387 kludgery causes the view of memory, as presented to 3388 record_gap/record_mapping, to actually reflect reality. IMO 3389 (JRS, 2010-Jan-03) the fact that /proc/.../maps does not list 3390 the commpage should be regarded as a bug in the kernel. */ 3391 { const Addr commpage_start = ARM_LINUX_FAKE_COMMPAGE_START; 3392 const Addr commpage_end1 = ARM_LINUX_FAKE_COMMPAGE_END1; 3393 if (gapStart < commpage_start) { 3394 if (record_gap) 3395 (*record_gap)( gapStart, commpage_start - gapStart ); 3396 if (record_mapping) 3397 (*record_mapping)( commpage_start, commpage_end1 - commpage_start, 3398 VKI_PROT_READ|VKI_PROT_EXEC, 3399 0/*dev*/, 0/*ino*/, 0/*foffset*/, 3400 NULL); 3401 gapStart = commpage_end1; 3402 } 3403 } 3404 # endif 3405 3406 if (record_gap && gapStart < Addr_MAX) 3407 (*record_gap) ( gapStart, Addr_MAX - gapStart + 1 ); 3408 } 3409 3410 /*------END-procmaps-parser-for-Linux----------------------------*/ 3411 3412 /*------BEGIN-procmaps-parser-for-Darwin-------------------------*/ 3413 3414 #elif defined(VGO_darwin) 3415 #include <mach/mach.h> 3416 #include <mach/mach_vm.h> 3417 3418 static unsigned int mach2vki(unsigned int vm_prot) 3419 { 3420 return 3421 ((vm_prot & VM_PROT_READ) ? VKI_PROT_READ : 0) | 3422 ((vm_prot & VM_PROT_WRITE) ? VKI_PROT_WRITE : 0) | 3423 ((vm_prot & VM_PROT_EXECUTE) ? VKI_PROT_EXEC : 0) ; 3424 } 3425 3426 static UInt stats_machcalls = 0; 3427 3428 static void parse_procselfmaps ( 3429 void (*record_mapping)( Addr addr, SizeT len, UInt prot, 3430 ULong dev, ULong ino, Off64T offset, 3431 const UChar* filename ), 3432 void (*record_gap)( Addr addr, SizeT len ) 3433 ) 3434 { 3435 vm_address_t iter; 3436 unsigned int depth; 3437 vm_address_t last; 3438 3439 iter = 0; 3440 depth = 0; 3441 last = 0; 3442 while (1) { 3443 mach_vm_address_t addr = iter; 3444 mach_vm_size_t size; 3445 vm_region_submap_short_info_data_64_t info; 3446 kern_return_t kr; 3447 3448 while (1) { 3449 mach_msg_type_number_t info_count 3450 = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64; 3451 stats_machcalls++; 3452 kr = mach_vm_region_recurse(mach_task_self(), &addr, &size, &depth, 3453 (vm_region_info_t)&info, &info_count); 3454 if (kr) 3455 return; 3456 if (info.is_submap) { 3457 depth++; 3458 continue; 3459 } 3460 break; 3461 } 3462 iter = addr + size; 3463 3464 if (addr > last && record_gap) { 3465 (*record_gap)(last, addr - last); 3466 } 3467 if (record_mapping) { 3468 (*record_mapping)(addr, size, mach2vki(info.protection), 3469 0, 0, info.offset, NULL); 3470 } 3471 last = addr + size; 3472 } 3473 3474 if ((Addr)-1 > last && record_gap) 3475 (*record_gap)(last, (Addr)-1 - last); 3476 } 3477 3478 // Urr. So much for thread safety. 3479 static Bool css_overflowed; 3480 static ChangedSeg* css_local; 3481 static Int css_size_local; 3482 static Int css_used_local; 3483 3484 static Addr Addr__max ( Addr a, Addr b ) { return a > b ? a : b; } 3485 static Addr Addr__min ( Addr a, Addr b ) { return a < b ? a : b; } 3486 3487 static void add_mapping_callback(Addr addr, SizeT len, UInt prot, 3488 ULong dev, ULong ino, Off64T offset, 3489 const UChar *filename) 3490 { 3491 // derived from sync_check_mapping_callback() 3492 3493 /* JRS 2012-Mar-07: this all seems very dubious to me. It would be 3494 safer to see if we can find, in V's segment collection, one 3495 single segment that completely covers the range [addr, +len) 3496 (and possibly more), and that has the exact same other 3497 properties (prot, dev, ino, offset, etc) as the data presented 3498 here. If found, we just skip. Otherwise add the data presented 3499 here into css_local[]. */ 3500 3501 Int iLo, iHi, i; 3502 3503 if (len == 0) return; 3504 3505 /* The kernel should not give us wraparounds. */ 3506 aspacem_assert(addr <= addr + len - 1); 3507 3508 iLo = find_nsegment_idx( addr ); 3509 iHi = find_nsegment_idx( addr + len - 1 ); 3510 3511 /* NSegments iLo .. iHi inclusive should agree with the presented 3512 data. */ 3513 for (i = iLo; i <= iHi; i++) { 3514 3515 UInt seg_prot; 3516 3517 if (nsegments[i].kind == SkAnonV || nsegments[i].kind == SkFileV) { 3518 /* Ignore V regions */ 3519 continue; 3520 } 3521 else if (nsegments[i].kind == SkFree || nsegments[i].kind == SkResvn) { 3522 /* Add mapping for SkResvn regions */ 3523 ChangedSeg* cs = &css_local[css_used_local]; 3524 if (css_used_local < css_size_local) { 3525 cs->is_added = True; 3526 cs->start = addr; 3527 cs->end = addr + len - 1; 3528 cs->prot = prot; 3529 cs->offset = offset; 3530 css_used_local++; 3531 } else { 3532 css_overflowed = True; 3533 } 3534 return; 3535 3536 } else if (nsegments[i].kind == SkAnonC || 3537 nsegments[i].kind == SkFileC || 3538 nsegments[i].kind == SkShmC) 3539 { 3540 /* Check permissions on client regions */ 3541 // GrP fixme 3542 seg_prot = 0; 3543 if (nsegments[i].hasR) seg_prot |= VKI_PROT_READ; 3544 if (nsegments[i].hasW) seg_prot |= VKI_PROT_WRITE; 3545 # if defined(VGA_x86) 3546 // GrP fixme sloppyXcheck 3547 // darwin: kernel X ignored and spuriously changes? (vm_copy) 3548 seg_prot |= (prot & VKI_PROT_EXEC); 3549 # else 3550 if (nsegments[i].hasX) seg_prot |= VKI_PROT_EXEC; 3551 # endif 3552 if (seg_prot != prot) { 3553 if (VG_(clo_trace_syscalls)) 3554 VG_(debugLog)(0,"aspacem","region %p..%p permission " 3555 "mismatch (kernel %x, V %x)\n", 3556 (void*)nsegments[i].start, 3557 (void*)(nsegments[i].end+1), prot, seg_prot); 3558 } 3559 3560 } else { 3561 aspacem_assert(0); 3562 } 3563 } 3564 } 3565 3566 static void remove_mapping_callback(Addr addr, SizeT len) 3567 { 3568 // derived from sync_check_gap_callback() 3569 3570 Int iLo, iHi, i; 3571 3572 if (len == 0) 3573 return; 3574 3575 /* The kernel should not give us wraparounds. */ 3576 aspacem_assert(addr <= addr + len - 1); 3577 3578 iLo = find_nsegment_idx( addr ); 3579 iHi = find_nsegment_idx( addr + len - 1 ); 3580 3581 /* NSegments iLo .. iHi inclusive should agree with the presented data. */ 3582 for (i = iLo; i <= iHi; i++) { 3583 if (nsegments[i].kind != SkFree && nsegments[i].kind != SkResvn) { 3584 /* V has a mapping, kernel doesn't. Add to css_local[], 3585 directives to chop off the part of the V mapping that 3586 falls within the gap that the kernel tells us is 3587 present. */ 3588 ChangedSeg* cs = &css_local[css_used_local]; 3589 if (css_used_local < css_size_local) { 3590 cs->is_added = False; 3591 cs->start = Addr__max(nsegments[i].start, addr); 3592 cs->end = Addr__min(nsegments[i].end, addr + len - 1); 3593 aspacem_assert(VG_IS_PAGE_ALIGNED(cs->start)); 3594 aspacem_assert(VG_IS_PAGE_ALIGNED(cs->end+1)); 3595 /* I don't think the following should fail. But if it 3596 does, just omit the css_used_local++ in the cases where 3597 it doesn't hold. */ 3598 aspacem_assert(cs->start < cs->end); 3599 cs->prot = 0; 3600 cs->offset = 0; 3601 css_used_local++; 3602 } else { 3603 css_overflowed = True; 3604 } 3605 } 3606 } 3607 } 3608 3609 3610 // Returns False if 'css' wasn't big enough. 3611 Bool VG_(get_changed_segments)( 3612 const HChar* when, const HChar* where, /*OUT*/ChangedSeg* css, 3613 Int css_size, /*OUT*/Int* css_used) 3614 { 3615 static UInt stats_synccalls = 1; 3616 aspacem_assert(when && where); 3617 3618 if (0) 3619 VG_(debugLog)(0,"aspacem", 3620 "[%u,%u] VG_(get_changed_segments)(%s, %s)\n", 3621 stats_synccalls++, stats_machcalls, when, where 3622 ); 3623 3624 css_overflowed = False; 3625 css_local = css; 3626 css_size_local = css_size; 3627 css_used_local = 0; 3628 3629 // Get the list of segs that need to be added/removed. 3630 parse_procselfmaps(&add_mapping_callback, &remove_mapping_callback); 3631 3632 *css_used = css_used_local; 3633 3634 if (css_overflowed) { 3635 aspacem_assert(css_used_local == css_size_local); 3636 } 3637 3638 return !css_overflowed; 3639 } 3640 3641 #endif // defined(VGO_darwin) 3642 3643 /*------END-procmaps-parser-for-Darwin---------------------------*/ 3644 3645 #endif // defined(VGO_linux) || defined(VGO_darwin) 3646 3647 /*--------------------------------------------------------------------*/ 3648 /*--- end ---*/ 3649 /*--------------------------------------------------------------------*/ 3650