os_dep.c 173 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939
  1. /*
  2. * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
  3. * Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
  4. * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
  5. * Copyright (c) 1999 by Hewlett-Packard Company. All rights reserved.
  6. * Copyright (c) 2008-2022 Ivan Maidanski
  7. *
  8. * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  9. * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
  10. *
  11. * Permission is hereby granted to use or copy this program
  12. * for any purpose, provided the above notices are retained on all copies.
  13. * Permission to modify the code and to distribute modified code is granted,
  14. * provided the above notices are retained, and a notice that the code was
  15. * modified is included with the above copyright notice.
  16. */
  17. #include "private/gc_priv.h"
  18. #if !defined(OS2) && !defined(PCR) && !defined(AMIGA) && !defined(MACOS) \
  19. && !defined(MSWINCE) && !defined(SN_TARGET_ORBIS) \
  20. && !defined(SN_TARGET_PSP2) && !defined(__CC_ARM)
  21. # include <sys/types.h>
  22. # if !defined(MSWIN32) && !defined(MSWIN_XBOX1)
  23. # include <unistd.h>
  24. # endif
  25. #endif
  26. #include <stdio.h>
  27. #if defined(MSWINCE) || defined(SN_TARGET_PS3)
  28. # define SIGSEGV 0 /* value is irrelevant */
  29. #else
  30. # include <signal.h>
  31. #endif
  32. #if defined(UNIX_LIKE) || defined(CYGWIN32) || defined(NACL) \
  33. || defined(SYMBIAN)
  34. # include <fcntl.h>
  35. #endif
  36. #if defined(LINUX) || defined(LINUX_STACKBOTTOM)
  37. # include <ctype.h>
  38. #endif
  39. /* Blatantly OS dependent routines, except for those that are related */
  40. /* to dynamic loading. */
  41. #ifdef AMIGA
  42. # define GC_AMIGA_DEF
  43. # include "extra/AmigaOS.c"
  44. # undef GC_AMIGA_DEF
  45. #endif
  46. #if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32)
  47. # ifndef WIN32_LEAN_AND_MEAN
  48. # define WIN32_LEAN_AND_MEAN 1
  49. # endif
  50. # define NOSERVICE
  51. # include <windows.h>
  52. /* It's not clear this is completely kosher under Cygwin. But it */
  53. /* allows us to get a working GC_get_stack_base. */
  54. #endif
  55. #ifdef MACOS
  56. # include <Processes.h>
  57. #endif
  58. #ifdef IRIX5
  59. # include <sys/uio.h>
  60. # include <malloc.h> /* for locking */
  61. #endif
  62. #if defined(MMAP_SUPPORTED) || defined(ADD_HEAP_GUARD_PAGES)
  63. # if defined(USE_MUNMAP) && !defined(USE_MMAP) && !defined(CPPCHECK)
  64. # error "invalid config - USE_MUNMAP requires USE_MMAP"
  65. # endif
  66. # include <sys/types.h>
  67. # include <sys/mman.h>
  68. # include <sys/stat.h>
  69. # include <errno.h>
  70. #endif
  71. #ifdef DARWIN
  72. /* for get_etext and friends */
  73. # include <mach-o/getsect.h>
  74. #endif
  75. #ifdef DJGPP
  76. /* Apparently necessary for djgpp 2.01. May cause problems with */
  77. /* other versions. */
  78. typedef long unsigned int caddr_t;
  79. #endif
  80. #ifdef PCR
  81. # include "il/PCR_IL.h"
  82. # include "th/PCR_ThCtl.h"
  83. # include "mm/PCR_MM.h"
  84. #endif
  85. #if defined(GC_DARWIN_THREADS) && defined(MPROTECT_VDB)
  86. /* Declare GC_mprotect_stop and GC_mprotect_resume as extern "C". */
  87. # include "private/darwin_stop_world.h"
  88. #endif
  89. #if !defined(NO_EXECUTE_PERMISSION)
  90. STATIC GC_bool GC_pages_executable = TRUE;
  91. #else
  92. STATIC GC_bool GC_pages_executable = FALSE;
  93. #endif
  94. #define IGNORE_PAGES_EXECUTABLE 1
  95. /* Undefined on GC_pages_executable real use. */
  96. #ifdef NEED_PROC_MAPS
  97. /* We need to parse /proc/self/maps, either to find dynamic libraries, */
  98. /* and/or to find the register backing store base (IA64). Do it once */
  99. /* here. */
  100. #define READ read
  101. /* Repeatedly perform a read call until the buffer is filled or */
  102. /* we encounter EOF. */
  103. STATIC ssize_t GC_repeat_read(int fd, char *buf, size_t count)
  104. {
  105. size_t num_read = 0;
  106. ASSERT_CANCEL_DISABLED();
  107. while (num_read < count) {
  108. ssize_t result = READ(fd, buf + num_read, count - num_read);
  109. if (result < 0) return result;
  110. if (result == 0) break;
  111. num_read += result;
  112. }
  113. return num_read;
  114. }
  115. #ifdef THREADS
  116. /* Determine the length of a file by incrementally reading it into a */
  117. /* buffer. This would be silly to use it on a file supporting lseek, */
  118. /* but Linux /proc files usually do not. */
  119. STATIC size_t GC_get_file_len(int f)
  120. {
  121. size_t total = 0;
  122. ssize_t result;
  123. # define GET_FILE_LEN_BUF_SZ 500
  124. char buf[GET_FILE_LEN_BUF_SZ];
  125. do {
  126. result = read(f, buf, GET_FILE_LEN_BUF_SZ);
  127. if (result == -1) return 0;
  128. total += result;
  129. } while (result > 0);
  130. return total;
  131. }
  132. STATIC size_t GC_get_maps_len(void)
  133. {
  134. int f = open("/proc/self/maps", O_RDONLY);
  135. size_t result;
  136. if (f < 0) return 0; /* treat missing file as empty */
  137. result = GC_get_file_len(f);
  138. close(f);
  139. return result;
  140. }
  141. #endif /* THREADS */
  142. /* Copy the contents of /proc/self/maps to a buffer in our address */
  143. /* space. Return the address of the buffer, or zero on failure. */
  144. /* This code could be simplified if we could determine its size ahead */
  145. /* of time. */
  146. GC_INNER char * GC_get_maps(void)
  147. {
  148. ssize_t result;
  149. static char *maps_buf = NULL;
  150. static size_t maps_buf_sz = 1;
  151. size_t maps_size, old_maps_size = 0;
  152. /* The buffer is essentially static, so there must be a single client. */
  153. GC_ASSERT(I_HOLD_LOCK());
  154. /* Note that in the presence of threads, the maps file can */
  155. /* essentially shrink asynchronously and unexpectedly as */
  156. /* threads that we already think of as dead release their */
  157. /* stacks. And there is no easy way to read the entire */
  158. /* file atomically. This is arguably a misfeature of the */
  159. /* /proc/.../maps interface. */
  160. /* Since we expect the file can grow asynchronously in rare */
  161. /* cases, it should suffice to first determine */
  162. /* the size (using lseek or read), and then to reread the */
  163. /* file. If the size is inconsistent we have to retry. */
  164. /* This only matters with threads enabled, and if we use */
  165. /* this to locate roots (not the default). */
  166. # ifdef THREADS
  167. /* Determine the initial size of /proc/self/maps. */
  168. /* Note that lseek doesn't work, at least as of 2.6.15. */
  169. maps_size = GC_get_maps_len();
  170. if (0 == maps_size) return 0;
  171. # else
  172. maps_size = 4000; /* Guess */
  173. # endif
  174. /* Read /proc/self/maps, growing maps_buf as necessary. */
  175. /* Note that we may not allocate conventionally, and */
  176. /* thus can't use stdio. */
  177. do {
  178. int f;
  179. while (maps_size >= maps_buf_sz) {
  180. GC_scratch_recycle_no_gww(maps_buf, maps_buf_sz);
  181. /* Grow only by powers of 2, since we leak "too small" buffers.*/
  182. while (maps_size >= maps_buf_sz) maps_buf_sz *= 2;
  183. maps_buf = GC_scratch_alloc(maps_buf_sz);
  184. # ifdef THREADS
  185. /* Recompute initial length, since we allocated. */
  186. /* This can only happen a few times per program */
  187. /* execution. */
  188. maps_size = GC_get_maps_len();
  189. if (0 == maps_size) return 0;
  190. # endif
  191. if (maps_buf == 0) return 0;
  192. }
  193. GC_ASSERT(maps_buf_sz >= maps_size + 1);
  194. f = open("/proc/self/maps", O_RDONLY);
  195. if (-1 == f) return 0;
  196. # ifdef THREADS
  197. old_maps_size = maps_size;
  198. # endif
  199. maps_size = 0;
  200. do {
  201. result = GC_repeat_read(f, maps_buf, maps_buf_sz-1);
  202. if (result <= 0)
  203. break;
  204. maps_size += result;
  205. } while ((size_t)result == maps_buf_sz-1);
  206. close(f);
  207. if (result <= 0)
  208. return 0;
  209. # ifdef THREADS
  210. if (maps_size > old_maps_size) {
  211. /* This might be caused by e.g. thread creation. */
  212. WARN("Unexpected asynchronous /proc/self/maps growth"
  213. " (to %" WARN_PRIdPTR " bytes)\n", maps_size);
  214. }
  215. # endif
  216. } while (maps_size >= maps_buf_sz || maps_size < old_maps_size);
  217. /* In the single-threaded case, the second clause is false. */
  218. maps_buf[maps_size] = '\0';
  219. return maps_buf;
  220. }
  221. /*
  222. * GC_parse_map_entry parses an entry from /proc/self/maps so we can
  223. * locate all writable data segments that belong to shared libraries.
  224. * The format of one of these entries and the fields we care about
  225. * is as follows:
  226. * XXXXXXXX-XXXXXXXX r-xp 00000000 30:05 260537 name of mapping...\n
  227. * ^^^^^^^^ ^^^^^^^^ ^^^^ ^^
  228. * start end prot maj_dev
  229. *
  230. * Note that since about august 2003 kernels, the columns no longer have
  231. * fixed offsets on 64-bit kernels. Hence we no longer rely on fixed offsets
  232. * anywhere, which is safer anyway.
  233. */
  234. /* Assign various fields of the first line in buf_ptr to (*start), */
  235. /* (*end), (*prot), (*maj_dev) and (*mapping_name). mapping_name may */
  236. /* be NULL. (*prot) and (*mapping_name) are assigned pointers into the */
  237. /* original buffer. */
  238. #if (defined(DYNAMIC_LOADING) && defined(USE_PROC_FOR_LIBRARIES)) \
  239. || defined(IA64) || defined(INCLUDE_LINUX_THREAD_DESCR) \
  240. || defined(REDIRECT_MALLOC)
  241. GC_INNER char *GC_parse_map_entry(char *buf_ptr, ptr_t *start, ptr_t *end,
  242. char **prot, unsigned int *maj_dev,
  243. char **mapping_name)
  244. {
  245. unsigned char *start_start, *end_start, *maj_dev_start;
  246. unsigned char *p; /* unsigned for isspace, isxdigit */
  247. if (buf_ptr == NULL || *buf_ptr == '\0') {
  248. return NULL;
  249. }
  250. p = (unsigned char *)buf_ptr;
  251. while (isspace(*p)) ++p;
  252. start_start = p;
  253. GC_ASSERT(isxdigit(*start_start));
  254. *start = (ptr_t)strtoul((char *)start_start, (char **)&p, 16);
  255. GC_ASSERT(*p=='-');
  256. ++p;
  257. end_start = p;
  258. GC_ASSERT(isxdigit(*end_start));
  259. *end = (ptr_t)strtoul((char *)end_start, (char **)&p, 16);
  260. GC_ASSERT(isspace(*p));
  261. while (isspace(*p)) ++p;
  262. GC_ASSERT(*p == 'r' || *p == '-');
  263. *prot = (char *)p;
  264. /* Skip past protection field to offset field */
  265. while (!isspace(*p)) ++p; while (isspace(*p)) ++p;
  266. GC_ASSERT(isxdigit(*p));
  267. /* Skip past offset field, which we ignore */
  268. while (!isspace(*p)) ++p; while (isspace(*p)) ++p;
  269. maj_dev_start = p;
  270. GC_ASSERT(isxdigit(*maj_dev_start));
  271. *maj_dev = strtoul((char *)maj_dev_start, NULL, 16);
  272. if (mapping_name == 0) {
  273. while (*p && *p++ != '\n');
  274. } else {
  275. while (*p && *p != '\n' && *p != '/' && *p != '[') p++;
  276. *mapping_name = (char *)p;
  277. while (*p && *p++ != '\n');
  278. }
  279. return (char *)p;
  280. }
  281. #endif /* REDIRECT_MALLOC || DYNAMIC_LOADING || IA64 || ... */
  282. #if defined(IA64) || defined(INCLUDE_LINUX_THREAD_DESCR)
  283. /* Try to read the backing store base from /proc/self/maps. */
  284. /* Return the bounds of the writable mapping with a 0 major device, */
  285. /* which includes the address passed as data. */
  286. /* Return FALSE if there is no such mapping. */
  287. GC_INNER GC_bool GC_enclosing_mapping(ptr_t addr, ptr_t *startp,
  288. ptr_t *endp)
  289. {
  290. char *prot;
  291. ptr_t my_start, my_end;
  292. unsigned int maj_dev;
  293. char *maps = GC_get_maps();
  294. char *buf_ptr = maps;
  295. if (0 == maps) return(FALSE);
  296. for (;;) {
  297. buf_ptr = GC_parse_map_entry(buf_ptr, &my_start, &my_end,
  298. &prot, &maj_dev, 0);
  299. if (buf_ptr == NULL) return FALSE;
  300. if (prot[1] == 'w' && maj_dev == 0) {
  301. if ((word)my_end > (word)addr && (word)my_start <= (word)addr) {
  302. *startp = my_start;
  303. *endp = my_end;
  304. return TRUE;
  305. }
  306. }
  307. }
  308. return FALSE;
  309. }
  310. #endif /* IA64 || INCLUDE_LINUX_THREAD_DESCR */
  311. #if defined(REDIRECT_MALLOC)
  312. /* Find the text(code) mapping for the library whose name, after */
  313. /* stripping the directory part, starts with nm. */
  314. GC_INNER GC_bool GC_text_mapping(char *nm, ptr_t *startp, ptr_t *endp)
  315. {
  316. size_t nm_len = strlen(nm);
  317. char *prot;
  318. char *map_path;
  319. ptr_t my_start, my_end;
  320. unsigned int maj_dev;
  321. char *maps = GC_get_maps();
  322. char *buf_ptr = maps;
  323. if (0 == maps) return(FALSE);
  324. for (;;) {
  325. buf_ptr = GC_parse_map_entry(buf_ptr, &my_start, &my_end,
  326. &prot, &maj_dev, &map_path);
  327. if (buf_ptr == NULL) return FALSE;
  328. if (prot[0] == 'r' && prot[1] == '-' && prot[2] == 'x') {
  329. char *p = map_path;
  330. /* Set p to point just past last slash, if any. */
  331. while (*p != '\0' && *p != '\n' && *p != ' ' && *p != '\t') ++p;
  332. while (*p != '/' && (word)p >= (word)map_path) --p;
  333. ++p;
  334. if (strncmp(nm, p, nm_len) == 0) {
  335. *startp = my_start;
  336. *endp = my_end;
  337. return TRUE;
  338. }
  339. }
  340. }
  341. return FALSE;
  342. }
  343. #endif /* REDIRECT_MALLOC */
  344. #ifdef IA64
  345. static ptr_t backing_store_base_from_proc(void)
  346. {
  347. ptr_t my_start, my_end;
  348. if (!GC_enclosing_mapping(GC_save_regs_in_stack(), &my_start, &my_end)) {
  349. GC_COND_LOG_PRINTF("Failed to find backing store base from /proc\n");
  350. return 0;
  351. }
  352. return my_start;
  353. }
  354. #endif
  355. #endif /* NEED_PROC_MAPS */
  356. #if defined(SEARCH_FOR_DATA_START)
  357. /* The I386 case can be handled without a search. The Alpha case */
  358. /* used to be handled differently as well, but the rules changed */
  359. /* for recent Linux versions. This seems to be the easiest way to */
  360. /* cover all versions. */
  361. # if defined(LINUX) || defined(HURD)
  362. /* Some Linux distributions arrange to define __data_start. Some */
  363. /* define data_start as a weak symbol. The latter is technically */
  364. /* broken, since the user program may define data_start, in which */
  365. /* case we lose. Nonetheless, we try both, preferring __data_start.*/
  366. /* We assume gcc-compatible pragmas. */
  367. EXTERN_C_BEGIN
  368. # pragma weak __data_start
  369. # pragma weak data_start
  370. extern int __data_start[], data_start[];
  371. # ifdef HOST_ANDROID
  372. # pragma weak _etext
  373. # pragma weak __dso_handle
  374. extern int _etext[], __dso_handle[];
  375. # endif
  376. EXTERN_C_END
  377. # endif /* LINUX */
  378. ptr_t GC_data_start = NULL;
  379. GC_INNER void GC_init_linux_data_start(void)
  380. {
  381. ptr_t data_end = DATAEND;
  382. # if (defined(LINUX) || defined(HURD)) && !defined(IGNORE_PROG_DATA_START)
  383. /* Try the easy approaches first: */
  384. # ifdef HOST_ANDROID
  385. /* Workaround for "gold" (default) linker (as of Android NDK r10e). */
  386. if ((word)__data_start < (word)_etext
  387. && (word)_etext < (word)__dso_handle) {
  388. GC_data_start = (ptr_t)(__dso_handle);
  389. # ifdef DEBUG_ADD_DEL_ROOTS
  390. GC_log_printf(
  391. "__data_start is wrong; using __dso_handle as data start\n");
  392. # endif
  393. } else
  394. # endif
  395. /* else */ if (COVERT_DATAFLOW(__data_start) != 0) {
  396. GC_data_start = (ptr_t)(__data_start);
  397. } else {
  398. GC_data_start = (ptr_t)(data_start);
  399. }
  400. if (COVERT_DATAFLOW(GC_data_start) != 0) {
  401. if ((word)GC_data_start > (word)data_end)
  402. ABORT_ARG2("Wrong __data_start/_end pair",
  403. ": %p .. %p", (void *)GC_data_start, (void *)data_end);
  404. return;
  405. }
  406. # ifdef DEBUG_ADD_DEL_ROOTS
  407. GC_log_printf("__data_start not provided\n");
  408. # endif
  409. # endif /* LINUX */
  410. if (GC_no_dls) {
  411. /* Not needed, avoids the SIGSEGV caused by */
  412. /* GC_find_limit which complicates debugging. */
  413. GC_data_start = data_end; /* set data root size to 0 */
  414. return;
  415. }
  416. GC_data_start = GC_find_limit(data_end, FALSE);
  417. }
  418. #endif /* SEARCH_FOR_DATA_START */
  419. #ifdef ECOS
  420. # ifndef ECOS_GC_MEMORY_SIZE
  421. # define ECOS_GC_MEMORY_SIZE (448 * 1024)
  422. # endif /* ECOS_GC_MEMORY_SIZE */
  423. /* FIXME: This is a simple way of allocating memory which is */
  424. /* compatible with ECOS early releases. Later releases use a more */
  425. /* sophisticated means of allocating memory than this simple static */
  426. /* allocator, but this method is at least bound to work. */
  427. static char ecos_gc_memory[ECOS_GC_MEMORY_SIZE];
  428. static char *ecos_gc_brk = ecos_gc_memory;
  429. static void *tiny_sbrk(ptrdiff_t increment)
  430. {
  431. void *p = ecos_gc_brk;
  432. ecos_gc_brk += increment;
  433. if ((word)ecos_gc_brk > (word)(ecos_gc_memory + sizeof(ecos_gc_memory))) {
  434. ecos_gc_brk -= increment;
  435. return NULL;
  436. }
  437. return p;
  438. }
  439. # define sbrk tiny_sbrk
  440. #endif /* ECOS */
  441. #if defined(NETBSD) && defined(__ELF__)
  442. ptr_t GC_data_start = NULL;
  443. EXTERN_C_BEGIN
  444. extern char **environ;
  445. EXTERN_C_END
  446. GC_INNER void GC_init_netbsd_elf(void)
  447. {
  448. /* This may need to be environ, without the underscore, for */
  449. /* some versions. */
  450. GC_data_start = GC_find_limit((ptr_t)&environ, FALSE);
  451. }
  452. #endif /* NETBSD */
  453. #if defined(ADDRESS_SANITIZER) && (defined(UNIX_LIKE) \
  454. || defined(NEED_FIND_LIMIT) || defined(MPROTECT_VDB)) \
  455. && !defined(CUSTOM_ASAN_DEF_OPTIONS)
  456. /* To tell ASan to allow GC to use its own SIGBUS/SEGV handlers. */
  457. /* The function is exported just to be visible to ASan library. */
  458. GC_API const char *__asan_default_options(void)
  459. {
  460. return "allow_user_segv_handler=1";
  461. }
  462. #endif
  463. #ifdef OPENBSD
  464. static struct sigaction old_segv_act;
  465. STATIC JMP_BUF GC_jmp_buf_openbsd;
  466. # ifdef THREADS
  467. # include <sys/syscall.h>
  468. EXTERN_C_BEGIN
  469. extern sigset_t __syscall(quad_t, ...);
  470. EXTERN_C_END
  471. # endif
  472. /* Don't use GC_find_limit() because siglongjmp() outside of the */
  473. /* signal handler by-passes our userland pthreads lib, leaving */
  474. /* SIGSEGV and SIGPROF masked. Instead, use this custom one that */
  475. /* works-around the issues. */
  476. STATIC void GC_fault_handler_openbsd(int sig GC_ATTR_UNUSED)
  477. {
  478. LONGJMP(GC_jmp_buf_openbsd, 1);
  479. }
  480. /* Return the first non-addressable location > p or bound. */
  481. /* Requires the allocation lock. */
  482. STATIC ptr_t GC_find_limit_openbsd(ptr_t p, ptr_t bound)
  483. {
  484. static volatile ptr_t result;
  485. /* Safer if static, since otherwise it may not be */
  486. /* preserved across the longjmp. Can safely be */
  487. /* static since it's only called with the */
  488. /* allocation lock held. */
  489. struct sigaction act;
  490. word pgsz = (word)sysconf(_SC_PAGESIZE);
  491. GC_ASSERT((word)bound >= pgsz);
  492. GC_ASSERT(I_HOLD_LOCK());
  493. act.sa_handler = GC_fault_handler_openbsd;
  494. sigemptyset(&act.sa_mask);
  495. act.sa_flags = SA_NODEFER | SA_RESTART;
  496. /* act.sa_restorer is deprecated and should not be initialized. */
  497. sigaction(SIGSEGV, &act, &old_segv_act);
  498. if (SETJMP(GC_jmp_buf_openbsd) == 0) {
  499. result = (ptr_t)((word)p & ~(pgsz-1));
  500. for (;;) {
  501. if ((word)result >= (word)bound - pgsz) {
  502. result = bound;
  503. break;
  504. }
  505. result += pgsz; /* no overflow expected */
  506. GC_noop1((word)(*result));
  507. }
  508. }
  509. # ifdef THREADS
  510. /* Due to the siglongjump we need to manually unmask SIGPROF. */
  511. __syscall(SYS_sigprocmask, SIG_UNBLOCK, sigmask(SIGPROF));
  512. # endif
  513. sigaction(SIGSEGV, &old_segv_act, 0);
  514. return(result);
  515. }
  516. /* Return first addressable location > p or bound. */
  517. /* Requires the allocation lock. */
  518. STATIC ptr_t GC_skip_hole_openbsd(ptr_t p, ptr_t bound)
  519. {
  520. static volatile ptr_t result;
  521. static volatile int firstpass;
  522. struct sigaction act;
  523. word pgsz = (word)sysconf(_SC_PAGESIZE);
  524. GC_ASSERT((word)bound >= pgsz);
  525. GC_ASSERT(I_HOLD_LOCK());
  526. act.sa_handler = GC_fault_handler_openbsd;
  527. sigemptyset(&act.sa_mask);
  528. act.sa_flags = SA_NODEFER | SA_RESTART;
  529. /* act.sa_restorer is deprecated and should not be initialized. */
  530. sigaction(SIGSEGV, &act, &old_segv_act);
  531. firstpass = 1;
  532. result = (ptr_t)((word)p & ~(pgsz-1));
  533. if (SETJMP(GC_jmp_buf_openbsd) != 0 || firstpass) {
  534. firstpass = 0;
  535. if ((word)result >= (word)bound - pgsz) {
  536. result = bound;
  537. } else {
  538. result += pgsz; /* no overflow expected */
  539. GC_noop1((word)(*result));
  540. }
  541. }
  542. sigaction(SIGSEGV, &old_segv_act, 0);
  543. return(result);
  544. }
  545. #endif /* OPENBSD */
  546. # ifdef OS2
  547. # include <stddef.h>
  548. # if !defined(__IBMC__) && !defined(__WATCOMC__) /* e.g. EMX */
  549. struct exe_hdr {
  550. unsigned short magic_number;
  551. unsigned short padding[29];
  552. long new_exe_offset;
  553. };
  554. #define E_MAGIC(x) (x).magic_number
  555. #define EMAGIC 0x5A4D
  556. #define E_LFANEW(x) (x).new_exe_offset
  557. struct e32_exe {
  558. unsigned char magic_number[2];
  559. unsigned char byte_order;
  560. unsigned char word_order;
  561. unsigned long exe_format_level;
  562. unsigned short cpu;
  563. unsigned short os;
  564. unsigned long padding1[13];
  565. unsigned long object_table_offset;
  566. unsigned long object_count;
  567. unsigned long padding2[31];
  568. };
  569. #define E32_MAGIC1(x) (x).magic_number[0]
  570. #define E32MAGIC1 'L'
  571. #define E32_MAGIC2(x) (x).magic_number[1]
  572. #define E32MAGIC2 'X'
  573. #define E32_BORDER(x) (x).byte_order
  574. #define E32LEBO 0
  575. #define E32_WORDER(x) (x).word_order
  576. #define E32LEWO 0
  577. #define E32_CPU(x) (x).cpu
  578. #define E32CPU286 1
  579. #define E32_OBJTAB(x) (x).object_table_offset
  580. #define E32_OBJCNT(x) (x).object_count
  581. struct o32_obj {
  582. unsigned long size;
  583. unsigned long base;
  584. unsigned long flags;
  585. unsigned long pagemap;
  586. unsigned long mapsize;
  587. unsigned long reserved;
  588. };
  589. #define O32_FLAGS(x) (x).flags
  590. #define OBJREAD 0x0001L
  591. #define OBJWRITE 0x0002L
  592. #define OBJINVALID 0x0080L
  593. #define O32_SIZE(x) (x).size
  594. #define O32_BASE(x) (x).base
  595. # else /* IBM's compiler */
  596. /* A kludge to get around what appears to be a header file bug */
  597. # ifndef WORD
  598. # define WORD unsigned short
  599. # endif
  600. # ifndef DWORD
  601. # define DWORD unsigned long
  602. # endif
  603. # define EXE386 1
  604. # include <newexe.h>
  605. # include <exe386.h>
  606. # endif /* __IBMC__ */
  607. # define INCL_DOSEXCEPTIONS
  608. # define INCL_DOSPROCESS
  609. # define INCL_DOSERRORS
  610. # define INCL_DOSMODULEMGR
  611. # define INCL_DOSMEMMGR
  612. # include <os2.h>
  613. # endif /* OS/2 */
  614. /* Find the page size */
  615. GC_INNER size_t GC_page_size = 0;
  616. #if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32)
  617. # ifndef VER_PLATFORM_WIN32_CE
  618. # define VER_PLATFORM_WIN32_CE 3
  619. # endif
  620. # if defined(MSWINCE) && defined(THREADS)
  621. GC_INNER GC_bool GC_dont_query_stack_min = FALSE;
  622. # endif
  623. GC_INNER SYSTEM_INFO GC_sysinfo;
  624. GC_INNER void GC_setpagesize(void)
  625. {
  626. GetSystemInfo(&GC_sysinfo);
  627. # if defined(CYGWIN32) && defined(USE_MUNMAP)
  628. /* Allocations made with mmap() are aligned to the allocation */
  629. /* granularity, which (at least on 64-bit Windows OS) is not the */
  630. /* same as the page size. Probably a separate variable could */
  631. /* be added to distinguish the allocation granularity from the */
  632. /* actual page size, but in practice there is no good reason to */
  633. /* make allocations smaller than dwAllocationGranularity, so we */
  634. /* just use it instead of the actual page size here (as Cygwin */
  635. /* itself does in many cases). */
  636. GC_page_size = (size_t)GC_sysinfo.dwAllocationGranularity;
  637. GC_ASSERT(GC_page_size >= (size_t)GC_sysinfo.dwPageSize);
  638. # else
  639. GC_page_size = (size_t)GC_sysinfo.dwPageSize;
  640. # endif
  641. # if defined(MSWINCE) && !defined(_WIN32_WCE_EMULATION)
  642. {
  643. OSVERSIONINFO verInfo;
  644. /* Check the current WinCE version. */
  645. verInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  646. if (!GetVersionEx(&verInfo))
  647. ABORT("GetVersionEx failed");
  648. if (verInfo.dwPlatformId == VER_PLATFORM_WIN32_CE &&
  649. verInfo.dwMajorVersion < 6) {
  650. /* Only the first 32 MB of address space belongs to the */
  651. /* current process (unless WinCE 6.0+ or emulation). */
  652. GC_sysinfo.lpMaximumApplicationAddress = (LPVOID)((word)32 << 20);
  653. # ifdef THREADS
  654. /* On some old WinCE versions, it's observed that */
  655. /* VirtualQuery calls don't work properly when used to */
  656. /* get thread current stack committed minimum. */
  657. if (verInfo.dwMajorVersion < 5)
  658. GC_dont_query_stack_min = TRUE;
  659. # endif
  660. }
  661. }
  662. # endif
  663. }
  664. # ifndef CYGWIN32
  665. # define is_writable(prot) ((prot) == PAGE_READWRITE \
  666. || (prot) == PAGE_WRITECOPY \
  667. || (prot) == PAGE_EXECUTE_READWRITE \
  668. || (prot) == PAGE_EXECUTE_WRITECOPY)
  669. /* Return the number of bytes that are writable starting at p. */
  670. /* The pointer p is assumed to be page aligned. */
  671. /* If base is not 0, *base becomes the beginning of the */
  672. /* allocation region containing p. */
  673. STATIC word GC_get_writable_length(ptr_t p, ptr_t *base)
  674. {
  675. MEMORY_BASIC_INFORMATION buf;
  676. word result;
  677. word protect;
  678. result = VirtualQuery(p, &buf, sizeof(buf));
  679. if (result != sizeof(buf)) ABORT("Weird VirtualQuery result");
  680. if (base != 0) *base = (ptr_t)(buf.AllocationBase);
  681. protect = (buf.Protect & ~(PAGE_GUARD | PAGE_NOCACHE));
  682. if (!is_writable(protect)) {
  683. return(0);
  684. }
  685. if (buf.State != MEM_COMMIT) return(0);
  686. return(buf.RegionSize);
  687. }
  688. GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *sb)
  689. {
  690. ptr_t trunc_sp;
  691. word size;
  692. /* Set page size if it is not ready (so client can use this */
  693. /* function even before GC is initialized). */
  694. if (!GC_page_size) GC_setpagesize();
  695. trunc_sp = (ptr_t)((word)GC_approx_sp() & ~(GC_page_size - 1));
  696. /* FIXME: This won't work if called from a deeply recursive */
  697. /* client code (and the committed stack space has grown). */
  698. size = GC_get_writable_length(trunc_sp, 0);
  699. GC_ASSERT(size != 0);
  700. sb -> mem_base = trunc_sp + size;
  701. return GC_SUCCESS;
  702. }
  703. # else /* CYGWIN32 */
  704. /* An alternate version for Cygwin (adapted from Dave Korn's */
  705. /* gcc version of boehm-gc). */
  706. GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *sb)
  707. {
  708. # ifdef X86_64
  709. sb -> mem_base = ((NT_TIB*)NtCurrentTeb())->StackBase;
  710. # else
  711. void * _tlsbase;
  712. __asm__ ("movl %%fs:4, %0"
  713. : "=r" (_tlsbase));
  714. sb -> mem_base = _tlsbase;
  715. # endif
  716. return GC_SUCCESS;
  717. }
  718. # endif /* CYGWIN32 */
  719. # define HAVE_GET_STACK_BASE
  720. #else /* !MSWIN32 */
  721. GC_INNER void GC_setpagesize(void)
  722. {
  723. # if defined(MPROTECT_VDB) || defined(PROC_VDB) || defined(USE_MMAP)
  724. GC_page_size = (size_t)GETPAGESIZE();
  725. # if !defined(CPPCHECK)
  726. if (0 == GC_page_size)
  727. ABORT("getpagesize failed");
  728. # endif
  729. # else
  730. /* It's acceptable to fake it. */
  731. GC_page_size = HBLKSIZE;
  732. # endif
  733. }
  734. #endif /* !MSWIN32 */
  735. #ifdef HAIKU
  736. # include <kernel/OS.h>
  737. GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *sb)
  738. {
  739. thread_info th;
  740. get_thread_info(find_thread(NULL),&th);
  741. sb->mem_base = th.stack_end;
  742. return GC_SUCCESS;
  743. }
  744. # define HAVE_GET_STACK_BASE
  745. #endif /* HAIKU */
  746. #ifdef OS2
  747. GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *sb)
  748. {
  749. PTIB ptib; /* thread information block */
  750. PPIB ppib;
  751. if (DosGetInfoBlocks(&ptib, &ppib) != NO_ERROR) {
  752. WARN("DosGetInfoBlocks failed\n", 0);
  753. return GC_UNIMPLEMENTED;
  754. }
  755. sb->mem_base = ptib->tib_pstacklimit;
  756. return GC_SUCCESS;
  757. }
  758. # define HAVE_GET_STACK_BASE
  759. #endif /* OS2 */
  760. # ifdef AMIGA
  761. # define GC_AMIGA_SB
  762. # include "extra/AmigaOS.c"
  763. # undef GC_AMIGA_SB
  764. # define GET_MAIN_STACKBASE_SPECIAL
  765. # endif /* AMIGA */
  766. # if defined(NEED_FIND_LIMIT) || defined(UNIX_LIKE)
  767. typedef void (*GC_fault_handler_t)(int);
  768. # if defined(SUNOS5SIGS) || defined(IRIX5) || defined(OSF1) \
  769. || defined(HAIKU) || defined(HURD) || defined(FREEBSD) \
  770. || defined(NETBSD)
  771. static struct sigaction old_segv_act;
  772. # if defined(_sigargs) /* !Irix6.x */ \
  773. || defined(HURD) || defined(NETBSD) || defined(FREEBSD)
  774. static struct sigaction old_bus_act;
  775. # endif
  776. # else
  777. static GC_fault_handler_t old_segv_handler;
  778. # ifdef HAVE_SIGBUS
  779. static GC_fault_handler_t old_bus_handler;
  780. # endif
  781. # endif
  782. GC_INNER void GC_set_and_save_fault_handler(GC_fault_handler_t h)
  783. {
  784. # if defined(SUNOS5SIGS) || defined(IRIX5) || defined(OSF1) \
  785. || defined(HAIKU) || defined(HURD) || defined(FREEBSD) \
  786. || defined(NETBSD)
  787. struct sigaction act;
  788. act.sa_handler = h;
  789. # ifdef SIGACTION_FLAGS_NODEFER_HACK
  790. /* Was necessary for Solaris 2.3 and very temporary */
  791. /* NetBSD bugs. */
  792. act.sa_flags = SA_RESTART | SA_NODEFER;
  793. # else
  794. act.sa_flags = SA_RESTART;
  795. # endif
  796. (void) sigemptyset(&act.sa_mask);
  797. /* act.sa_restorer is deprecated and should not be initialized. */
  798. # ifdef GC_IRIX_THREADS
  799. /* Older versions have a bug related to retrieving and */
  800. /* and setting a handler at the same time. */
  801. (void) sigaction(SIGSEGV, 0, &old_segv_act);
  802. (void) sigaction(SIGSEGV, &act, 0);
  803. # else
  804. (void) sigaction(SIGSEGV, &act, &old_segv_act);
  805. # if defined(IRIX5) && defined(_sigargs) /* Irix 5.x, not 6.x */ \
  806. || defined(HURD) || defined(NETBSD) || defined(FREEBSD)
  807. /* Under Irix 5.x or HP/UX, we may get SIGBUS. */
  808. /* Pthreads doesn't exist under Irix 5.x, so we */
  809. /* don't have to worry in the threads case. */
  810. (void) sigaction(SIGBUS, &act, &old_bus_act);
  811. # endif
  812. # endif /* !GC_IRIX_THREADS */
  813. # else
  814. old_segv_handler = signal(SIGSEGV, h);
  815. # ifdef HAVE_SIGBUS
  816. old_bus_handler = signal(SIGBUS, h);
  817. # endif
  818. # endif
  819. # if defined(CPPCHECK) && defined(ADDRESS_SANITIZER)
  820. GC_noop1((word)&__asan_default_options);
  821. # endif
  822. }
  823. # endif /* NEED_FIND_LIMIT || UNIX_LIKE */
  824. # if defined(NEED_FIND_LIMIT) \
  825. || (defined(USE_PROC_FOR_LIBRARIES) && defined(THREADS))
  826. /* Some tools to implement HEURISTIC2 */
  827. # define MIN_PAGE_SIZE 256 /* Smallest conceivable page size, bytes */
  828. GC_INNER JMP_BUF GC_jmp_buf;
  829. STATIC void GC_fault_handler(int sig GC_ATTR_UNUSED)
  830. {
  831. LONGJMP(GC_jmp_buf, 1);
  832. }
  833. GC_INNER void GC_setup_temporary_fault_handler(void)
  834. {
  835. /* Handler is process-wide, so this should only happen in */
  836. /* one thread at a time. */
  837. GC_ASSERT(I_HOLD_LOCK());
  838. GC_set_and_save_fault_handler(GC_fault_handler);
  839. }
  840. GC_INNER void GC_reset_fault_handler(void)
  841. {
  842. # if defined(SUNOS5SIGS) || defined(IRIX5) || defined(OSF1) \
  843. || defined(HAIKU) || defined(HURD) || defined(FREEBSD) \
  844. || defined(NETBSD)
  845. (void) sigaction(SIGSEGV, &old_segv_act, 0);
  846. # if defined(IRIX5) && defined(_sigargs) /* Irix 5.x, not 6.x */ \
  847. || defined(HURD) || defined(NETBSD)
  848. (void) sigaction(SIGBUS, &old_bus_act, 0);
  849. # endif
  850. # else
  851. (void) signal(SIGSEGV, old_segv_handler);
  852. # ifdef HAVE_SIGBUS
  853. (void) signal(SIGBUS, old_bus_handler);
  854. # endif
  855. # endif
  856. }
  857. /* Return the first non-addressable location > p (up) or */
  858. /* the smallest location q s.t. [q,p) is addressable (!up). */
  859. /* We assume that p (up) or p-1 (!up) is addressable. */
  860. /* Requires allocation lock. */
  861. STATIC ptr_t GC_find_limit_with_bound(ptr_t p, GC_bool up, ptr_t bound)
  862. {
  863. static volatile ptr_t result;
  864. /* Safer if static, since otherwise it may not be */
  865. /* preserved across the longjmp. Can safely be */
  866. /* static since it's only called with the */
  867. /* allocation lock held. */
  868. GC_ASSERT(up ? (word)bound >= MIN_PAGE_SIZE
  869. : (word)bound <= ~(word)MIN_PAGE_SIZE);
  870. GC_ASSERT(I_HOLD_LOCK());
  871. GC_setup_temporary_fault_handler();
  872. if (SETJMP(GC_jmp_buf) == 0) {
  873. result = (ptr_t)(((word)(p))
  874. & ~(MIN_PAGE_SIZE-1));
  875. for (;;) {
  876. if (up) {
  877. if ((word)result >= (word)bound - MIN_PAGE_SIZE) {
  878. result = bound;
  879. break;
  880. }
  881. result += MIN_PAGE_SIZE; /* no overflow expected */
  882. } else {
  883. if ((word)result <= (word)bound + MIN_PAGE_SIZE) {
  884. result = bound - MIN_PAGE_SIZE;
  885. /* This is to compensate */
  886. /* further result increment (we */
  887. /* do not modify "up" variable */
  888. /* since it might be clobbered */
  889. /* by setjmp otherwise). */
  890. break;
  891. }
  892. result -= MIN_PAGE_SIZE; /* no underflow expected */
  893. }
  894. GC_noop1((word)(*result));
  895. }
  896. }
  897. GC_reset_fault_handler();
  898. if (!up) {
  899. result += MIN_PAGE_SIZE;
  900. }
  901. return(result);
  902. }
  903. ptr_t GC_find_limit(ptr_t p, GC_bool up)
  904. {
  905. return GC_find_limit_with_bound(p, up, up ? (ptr_t)(word)(-1) : 0);
  906. }
  907. # endif /* NEED_FIND_LIMIT || USE_PROC_FOR_LIBRARIES */
  908. #ifdef HPUX_STACKBOTTOM
  909. #include <sys/param.h>
  910. #include <sys/pstat.h>
  911. GC_INNER ptr_t GC_get_register_stack_base(void)
  912. {
  913. struct pst_vm_status vm_status;
  914. int i = 0;
  915. while (pstat_getprocvm(&vm_status, sizeof(vm_status), 0, i++) == 1) {
  916. if (vm_status.pst_type == PS_RSESTACK) {
  917. return (ptr_t) vm_status.pst_vaddr;
  918. }
  919. }
  920. /* old way to get the register stackbottom */
  921. return (ptr_t)(((word)GC_stackbottom - BACKING_STORE_DISPLACEMENT - 1)
  922. & ~(BACKING_STORE_ALIGNMENT - 1));
  923. }
  924. #endif /* HPUX_STACK_BOTTOM */
  925. #ifdef LINUX_STACKBOTTOM
  926. # include <sys/types.h>
  927. # include <sys/stat.h>
  928. # define STAT_SKIP 27 /* Number of fields preceding startstack */
  929. /* field in /proc/self/stat */
  930. # ifdef USE_LIBC_PRIVATES
  931. EXTERN_C_BEGIN
  932. # pragma weak __libc_stack_end
  933. extern ptr_t __libc_stack_end;
  934. # ifdef IA64
  935. # pragma weak __libc_ia64_register_backing_store_base
  936. extern ptr_t __libc_ia64_register_backing_store_base;
  937. # endif
  938. EXTERN_C_END
  939. # endif
  940. # ifdef IA64
  941. GC_INNER ptr_t GC_get_register_stack_base(void)
  942. {
  943. ptr_t result;
  944. # ifdef USE_LIBC_PRIVATES
  945. if (0 != &__libc_ia64_register_backing_store_base
  946. && 0 != __libc_ia64_register_backing_store_base) {
  947. /* Glibc 2.2.4 has a bug such that for dynamically linked */
  948. /* executables __libc_ia64_register_backing_store_base is */
  949. /* defined but uninitialized during constructor calls. */
  950. /* Hence we check for both nonzero address and value. */
  951. return __libc_ia64_register_backing_store_base;
  952. }
  953. # endif
  954. result = backing_store_base_from_proc();
  955. if (0 == result) {
  956. result = GC_find_limit(GC_save_regs_in_stack(), FALSE);
  957. /* Now seems to work better than constant displacement */
  958. /* heuristic used in 6.X versions. The latter seems to */
  959. /* fail for 2.6 kernels. */
  960. }
  961. return result;
  962. }
  963. # endif /* IA64 */
  964. STATIC ptr_t GC_linux_main_stack_base(void)
  965. {
  966. /* We read the stack base value from /proc/self/stat. We do this */
  967. /* using direct I/O system calls in order to avoid calling malloc */
  968. /* in case REDIRECT_MALLOC is defined. */
  969. # ifndef STAT_READ
  970. /* Also defined in pthread_support.c. */
  971. # define STAT_BUF_SIZE 4096
  972. # define STAT_READ read
  973. # endif
  974. /* Should probably call the real read, if read is wrapped. */
  975. char stat_buf[STAT_BUF_SIZE];
  976. int f;
  977. word result;
  978. int i, buf_offset = 0, len;
  979. /* First try the easy way. This should work for glibc 2.2 */
  980. /* This fails in a prelinked ("prelink" command) executable */
  981. /* since the correct value of __libc_stack_end never */
  982. /* becomes visible to us. The second test works around */
  983. /* this. */
  984. # ifdef USE_LIBC_PRIVATES
  985. if (0 != &__libc_stack_end && 0 != __libc_stack_end ) {
  986. # if defined(IA64)
  987. /* Some versions of glibc set the address 16 bytes too */
  988. /* low while the initialization code is running. */
  989. if (((word)__libc_stack_end & 0xfff) + 0x10 < 0x1000) {
  990. return __libc_stack_end + 0x10;
  991. } /* Otherwise it's not safe to add 16 bytes and we fall */
  992. /* back to using /proc. */
  993. # elif defined(SPARC)
  994. /* Older versions of glibc for 64-bit SPARC do not set this */
  995. /* variable correctly, it gets set to either zero or one. */
  996. if (__libc_stack_end != (ptr_t) (unsigned long)0x1)
  997. return __libc_stack_end;
  998. # else
  999. return __libc_stack_end;
  1000. # endif
  1001. }
  1002. # endif
  1003. f = open("/proc/self/stat", O_RDONLY);
  1004. if (f < 0)
  1005. ABORT("Couldn't read /proc/self/stat");
  1006. len = STAT_READ(f, stat_buf, STAT_BUF_SIZE);
  1007. close(f);
  1008. /* Skip the required number of fields. This number is hopefully */
  1009. /* constant across all Linux implementations. */
  1010. for (i = 0; i < STAT_SKIP; ++i) {
  1011. while (buf_offset < len && isspace(stat_buf[buf_offset++])) {
  1012. /* empty */
  1013. }
  1014. while (buf_offset < len && !isspace(stat_buf[buf_offset++])) {
  1015. /* empty */
  1016. }
  1017. }
  1018. /* Skip spaces. */
  1019. while (buf_offset < len && isspace(stat_buf[buf_offset])) {
  1020. buf_offset++;
  1021. }
  1022. /* Find the end of the number and cut the buffer there. */
  1023. for (i = 0; buf_offset + i < len; i++) {
  1024. if (!isdigit(stat_buf[buf_offset + i])) break;
  1025. }
  1026. if (buf_offset + i >= len) ABORT("Could not parse /proc/self/stat");
  1027. stat_buf[buf_offset + i] = '\0';
  1028. result = (word)STRTOULL(&stat_buf[buf_offset], NULL, 10);
  1029. if (result < 0x100000 || (result & (sizeof(word) - 1)) != 0)
  1030. ABORT("Absurd stack bottom value");
  1031. return (ptr_t)result;
  1032. }
  1033. #endif /* LINUX_STACKBOTTOM */
  1034. #ifdef FREEBSD_STACKBOTTOM
  1035. /* This uses an undocumented sysctl call, but at least one expert */
  1036. /* believes it will stay. */
  1037. # include <unistd.h>
  1038. # include <sys/types.h>
  1039. # include <sys/sysctl.h>
  1040. STATIC ptr_t GC_freebsd_main_stack_base(void)
  1041. {
  1042. int nm[2] = {CTL_KERN, KERN_USRSTACK};
  1043. ptr_t base;
  1044. size_t len = sizeof(ptr_t);
  1045. int r = sysctl(nm, 2, &base, &len, NULL, 0);
  1046. if (r) ABORT("Error getting main stack base");
  1047. return base;
  1048. }
  1049. #endif /* FREEBSD_STACKBOTTOM */
  1050. #if defined(ECOS) || defined(NOSYS)
  1051. ptr_t GC_get_main_stack_base(void)
  1052. {
  1053. return STACKBOTTOM;
  1054. }
  1055. # define GET_MAIN_STACKBASE_SPECIAL
  1056. #elif defined(SYMBIAN)
  1057. EXTERN_C_BEGIN
  1058. extern int GC_get_main_symbian_stack_base(void);
  1059. EXTERN_C_END
  1060. ptr_t GC_get_main_stack_base(void)
  1061. {
  1062. return (ptr_t)GC_get_main_symbian_stack_base();
  1063. }
  1064. # define GET_MAIN_STACKBASE_SPECIAL
  1065. #elif !defined(AMIGA) && !defined(HAIKU) && !defined(OS2) \
  1066. && !defined(MSWIN32) && !defined(MSWINCE) && !defined(CYGWIN32) \
  1067. && !defined(GC_OPENBSD_THREADS) \
  1068. && (!defined(GC_SOLARIS_THREADS) || defined(_STRICT_STDC))
  1069. # if (defined(HAVE_PTHREAD_ATTR_GET_NP) || defined(HAVE_PTHREAD_GETATTR_NP)) \
  1070. && (defined(THREADS) || defined(USE_GET_STACKBASE_FOR_MAIN))
  1071. # include <pthread.h>
  1072. # ifdef HAVE_PTHREAD_NP_H
  1073. # include <pthread_np.h> /* for pthread_attr_get_np() */
  1074. # endif
  1075. # elif defined(DARWIN) && !defined(NO_PTHREAD_GET_STACKADDR_NP)
  1076. /* We could use pthread_get_stackaddr_np even in case of a */
  1077. /* single-threaded gclib (there is no -lpthread on Darwin). */
  1078. # include <pthread.h>
  1079. # undef STACKBOTTOM
  1080. # define STACKBOTTOM (ptr_t)pthread_get_stackaddr_np(pthread_self())
  1081. # endif
  1082. ptr_t GC_get_main_stack_base(void)
  1083. {
  1084. ptr_t result;
  1085. # if (defined(HAVE_PTHREAD_ATTR_GET_NP) \
  1086. || defined(HAVE_PTHREAD_GETATTR_NP)) \
  1087. && (defined(USE_GET_STACKBASE_FOR_MAIN) \
  1088. || (defined(THREADS) && !defined(REDIRECT_MALLOC)))
  1089. pthread_attr_t attr;
  1090. void *stackaddr;
  1091. size_t size;
  1092. # ifdef HAVE_PTHREAD_ATTR_GET_NP
  1093. if (pthread_attr_init(&attr) == 0
  1094. && (pthread_attr_get_np(pthread_self(), &attr) == 0
  1095. ? TRUE : (pthread_attr_destroy(&attr), FALSE)))
  1096. # else /* HAVE_PTHREAD_GETATTR_NP */
  1097. if (pthread_getattr_np(pthread_self(), &attr) == 0)
  1098. # endif
  1099. {
  1100. if (pthread_attr_getstack(&attr, &stackaddr, &size) == 0
  1101. && stackaddr != NULL) {
  1102. (void)pthread_attr_destroy(&attr);
  1103. # ifdef STACK_GROWS_DOWN
  1104. stackaddr = (char *)stackaddr + size;
  1105. # endif
  1106. return (ptr_t)stackaddr;
  1107. }
  1108. (void)pthread_attr_destroy(&attr);
  1109. }
  1110. WARN("pthread_getattr_np or pthread_attr_getstack failed"
  1111. " for main thread\n", 0);
  1112. # endif
  1113. # ifdef STACKBOTTOM
  1114. result = STACKBOTTOM;
  1115. # else
  1116. # define STACKBOTTOM_ALIGNMENT_M1 ((word)STACK_GRAN - 1)
  1117. # ifdef HEURISTIC1
  1118. # ifdef STACK_GROWS_DOWN
  1119. result = (ptr_t)(((word)GC_approx_sp() + STACKBOTTOM_ALIGNMENT_M1)
  1120. & ~STACKBOTTOM_ALIGNMENT_M1);
  1121. # else
  1122. result = (ptr_t)((word)GC_approx_sp() & ~STACKBOTTOM_ALIGNMENT_M1);
  1123. # endif
  1124. # elif defined(LINUX_STACKBOTTOM)
  1125. result = GC_linux_main_stack_base();
  1126. # elif defined(FREEBSD_STACKBOTTOM)
  1127. result = GC_freebsd_main_stack_base();
  1128. # elif defined(HEURISTIC2)
  1129. {
  1130. ptr_t sp = GC_approx_sp();
  1131. # ifdef STACK_GROWS_DOWN
  1132. result = GC_find_limit(sp, TRUE);
  1133. # if defined(HEURISTIC2_LIMIT) && !defined(CPPCHECK)
  1134. if ((word)result > (word)HEURISTIC2_LIMIT
  1135. && (word)sp < (word)HEURISTIC2_LIMIT) {
  1136. result = HEURISTIC2_LIMIT;
  1137. }
  1138. # endif
  1139. # else
  1140. result = GC_find_limit(sp, FALSE);
  1141. # if defined(HEURISTIC2_LIMIT) && !defined(CPPCHECK)
  1142. if ((word)result < (word)HEURISTIC2_LIMIT
  1143. && (word)sp > (word)HEURISTIC2_LIMIT) {
  1144. result = HEURISTIC2_LIMIT;
  1145. }
  1146. # endif
  1147. # endif
  1148. }
  1149. # elif defined(STACK_NOT_SCANNED) || defined(CPPCHECK)
  1150. result = NULL;
  1151. # else
  1152. # error None of HEURISTIC* and *STACKBOTTOM defined!
  1153. # endif
  1154. # if defined(STACK_GROWS_DOWN) && !defined(CPPCHECK)
  1155. if (result == 0)
  1156. result = (ptr_t)(signed_word)(-sizeof(ptr_t));
  1157. # endif
  1158. # endif
  1159. GC_ASSERT((word)GC_approx_sp() HOTTER_THAN (word)result);
  1160. return(result);
  1161. }
  1162. # define GET_MAIN_STACKBASE_SPECIAL
  1163. #endif /* !AMIGA, !HAIKU, !OPENBSD, !OS2, !Windows */
  1164. #if (defined(HAVE_PTHREAD_ATTR_GET_NP) || defined(HAVE_PTHREAD_GETATTR_NP)) \
  1165. && defined(THREADS) && !defined(HAVE_GET_STACK_BASE)
  1166. # include <pthread.h>
  1167. # ifdef HAVE_PTHREAD_NP_H
  1168. # include <pthread_np.h>
  1169. # endif
  1170. GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *b)
  1171. {
  1172. pthread_attr_t attr;
  1173. size_t size;
  1174. # ifdef IA64
  1175. DCL_LOCK_STATE;
  1176. # endif
  1177. # ifdef HAVE_PTHREAD_ATTR_GET_NP
  1178. if (pthread_attr_init(&attr) != 0)
  1179. ABORT("pthread_attr_init failed");
  1180. if (pthread_attr_get_np(pthread_self(), &attr) != 0) {
  1181. WARN("pthread_attr_get_np failed\n", 0);
  1182. (void)pthread_attr_destroy(&attr);
  1183. return GC_UNIMPLEMENTED;
  1184. }
  1185. # else /* HAVE_PTHREAD_GETATTR_NP */
  1186. if (pthread_getattr_np(pthread_self(), &attr) != 0) {
  1187. WARN("pthread_getattr_np failed\n", 0);
  1188. return GC_UNIMPLEMENTED;
  1189. }
  1190. # endif
  1191. if (pthread_attr_getstack(&attr, &(b -> mem_base), &size) != 0) {
  1192. ABORT("pthread_attr_getstack failed");
  1193. }
  1194. (void)pthread_attr_destroy(&attr);
  1195. # ifdef STACK_GROWS_DOWN
  1196. b -> mem_base = (char *)(b -> mem_base) + size;
  1197. # endif
  1198. # ifdef IA64
  1199. /* We could try backing_store_base_from_proc, but that's safe */
  1200. /* only if no mappings are being asynchronously created. */
  1201. /* Subtracting the size from the stack base doesn't work for at */
  1202. /* least the main thread. */
  1203. LOCK();
  1204. {
  1205. IF_CANCEL(int cancel_state;)
  1206. ptr_t bsp;
  1207. ptr_t next_stack;
  1208. DISABLE_CANCEL(cancel_state);
  1209. bsp = GC_save_regs_in_stack();
  1210. next_stack = GC_greatest_stack_base_below(bsp);
  1211. if (0 == next_stack) {
  1212. b -> reg_base = GC_find_limit(bsp, FALSE);
  1213. } else {
  1214. /* Avoid walking backwards into preceding memory stack and */
  1215. /* growing it. */
  1216. b -> reg_base = GC_find_limit_with_bound(bsp, FALSE, next_stack);
  1217. }
  1218. RESTORE_CANCEL(cancel_state);
  1219. }
  1220. UNLOCK();
  1221. # endif
  1222. return GC_SUCCESS;
  1223. }
  1224. # define HAVE_GET_STACK_BASE
  1225. #endif /* THREADS && (HAVE_PTHREAD_ATTR_GET_NP || HAVE_PTHREAD_GETATTR_NP) */
  1226. #if defined(GC_DARWIN_THREADS) && !defined(NO_PTHREAD_GET_STACKADDR_NP)
  1227. # include <pthread.h>
  1228. GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *b)
  1229. {
  1230. /* pthread_get_stackaddr_np() should return stack bottom (highest */
  1231. /* stack address plus 1). */
  1232. b->mem_base = pthread_get_stackaddr_np(pthread_self());
  1233. GC_ASSERT((word)GC_approx_sp() HOTTER_THAN (word)b->mem_base);
  1234. return GC_SUCCESS;
  1235. }
  1236. # define HAVE_GET_STACK_BASE
  1237. #endif /* GC_DARWIN_THREADS */
  1238. #ifdef GC_OPENBSD_THREADS
  1239. # include <sys/signal.h>
  1240. # include <pthread.h>
  1241. # include <pthread_np.h>
  1242. /* Find the stack using pthread_stackseg_np(). */
  1243. GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *sb)
  1244. {
  1245. stack_t stack;
  1246. if (pthread_stackseg_np(pthread_self(), &stack))
  1247. ABORT("pthread_stackseg_np(self) failed");
  1248. sb->mem_base = stack.ss_sp;
  1249. return GC_SUCCESS;
  1250. }
  1251. # define HAVE_GET_STACK_BASE
  1252. #endif /* GC_OPENBSD_THREADS */
  1253. #if defined(GC_SOLARIS_THREADS) && !defined(_STRICT_STDC)
  1254. # include <thread.h>
  1255. # include <signal.h>
  1256. # include <pthread.h>
  1257. /* These variables are used to cache ss_sp value for the primordial */
  1258. /* thread (it's better not to call thr_stksegment() twice for this */
  1259. /* thread - see JDK bug #4352906). */
  1260. static pthread_t stackbase_main_self = 0;
  1261. /* 0 means stackbase_main_ss_sp value is unset. */
  1262. static void *stackbase_main_ss_sp = NULL;
  1263. GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *b)
  1264. {
  1265. stack_t s;
  1266. pthread_t self = pthread_self();
  1267. if (self == stackbase_main_self)
  1268. {
  1269. /* If the client calls GC_get_stack_base() from the main thread */
  1270. /* then just return the cached value. */
  1271. b -> mem_base = stackbase_main_ss_sp;
  1272. GC_ASSERT(b -> mem_base != NULL);
  1273. return GC_SUCCESS;
  1274. }
  1275. if (thr_stksegment(&s)) {
  1276. /* According to the manual, the only failure error code returned */
  1277. /* is EAGAIN meaning "the information is not available due to the */
  1278. /* thread is not yet completely initialized or it is an internal */
  1279. /* thread" - this shouldn't happen here. */
  1280. ABORT("thr_stksegment failed");
  1281. }
  1282. /* s.ss_sp holds the pointer to the stack bottom. */
  1283. GC_ASSERT((word)GC_approx_sp() HOTTER_THAN (word)s.ss_sp);
  1284. if (!stackbase_main_self && thr_main() != 0)
  1285. {
  1286. /* Cache the stack base value for the primordial thread (this */
  1287. /* is done during GC_init, so there is no race). */
  1288. stackbase_main_ss_sp = s.ss_sp;
  1289. stackbase_main_self = self;
  1290. }
  1291. b -> mem_base = s.ss_sp;
  1292. return GC_SUCCESS;
  1293. }
  1294. # define HAVE_GET_STACK_BASE
  1295. #endif /* GC_SOLARIS_THREADS */
  1296. #ifdef GC_RTEMS_PTHREADS
  1297. GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *sb)
  1298. {
  1299. sb->mem_base = rtems_get_stack_bottom();
  1300. return GC_SUCCESS;
  1301. }
  1302. # define HAVE_GET_STACK_BASE
  1303. #endif /* GC_RTEMS_PTHREADS */
  1304. #ifndef HAVE_GET_STACK_BASE
  1305. # ifdef NEED_FIND_LIMIT
  1306. /* Retrieve stack base. */
  1307. /* Using the GC_find_limit version is risky. */
  1308. /* On IA64, for example, there is no guard page between the */
  1309. /* stack of one thread and the register backing store of the */
  1310. /* next. Thus this is likely to identify way too large a */
  1311. /* "stack" and thus at least result in disastrous performance. */
  1312. /* FIXME - Implement better strategies here. */
  1313. GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *b)
  1314. {
  1315. IF_CANCEL(int cancel_state;)
  1316. DCL_LOCK_STATE;
  1317. LOCK();
  1318. DISABLE_CANCEL(cancel_state); /* May be unnecessary? */
  1319. # ifdef STACK_GROWS_DOWN
  1320. b -> mem_base = GC_find_limit(GC_approx_sp(), TRUE);
  1321. # ifdef IA64
  1322. b -> reg_base = GC_find_limit(GC_save_regs_in_stack(), FALSE);
  1323. # endif
  1324. # else
  1325. b -> mem_base = GC_find_limit(GC_approx_sp(), FALSE);
  1326. # endif
  1327. RESTORE_CANCEL(cancel_state);
  1328. UNLOCK();
  1329. return GC_SUCCESS;
  1330. }
  1331. # else
  1332. GC_API int GC_CALL GC_get_stack_base(
  1333. struct GC_stack_base *b GC_ATTR_UNUSED)
  1334. {
  1335. # if defined(GET_MAIN_STACKBASE_SPECIAL) && !defined(THREADS) \
  1336. && !defined(IA64)
  1337. b->mem_base = GC_get_main_stack_base();
  1338. return GC_SUCCESS;
  1339. # else
  1340. return GC_UNIMPLEMENTED;
  1341. # endif
  1342. }
  1343. # endif /* !NEED_FIND_LIMIT */
  1344. #endif /* !HAVE_GET_STACK_BASE */
  1345. #ifndef GET_MAIN_STACKBASE_SPECIAL
  1346. /* This is always called from the main thread. Default implementation. */
  1347. ptr_t GC_get_main_stack_base(void)
  1348. {
  1349. struct GC_stack_base sb;
  1350. if (GC_get_stack_base(&sb) != GC_SUCCESS)
  1351. ABORT("GC_get_stack_base failed");
  1352. GC_ASSERT((word)GC_approx_sp() HOTTER_THAN (word)sb.mem_base);
  1353. return (ptr_t)sb.mem_base;
  1354. }
  1355. #endif /* !GET_MAIN_STACKBASE_SPECIAL */
  1356. /* Register static data segment(s) as roots. If more data segments are */
  1357. /* added later then they need to be registered at that point (as we do */
  1358. /* with SunOS dynamic loading), or GC_mark_roots needs to check for */
  1359. /* them (as we do with PCR). Called with allocator lock held. */
  1360. # ifdef OS2
  1361. void GC_register_data_segments(void)
  1362. {
  1363. PTIB ptib;
  1364. PPIB ppib;
  1365. HMODULE module_handle;
  1366. # define PBUFSIZ 512
  1367. UCHAR path[PBUFSIZ];
  1368. FILE * myexefile;
  1369. struct exe_hdr hdrdos; /* MSDOS header. */
  1370. struct e32_exe hdr386; /* Real header for my executable */
  1371. struct o32_obj seg; /* Current segment */
  1372. int nsegs;
  1373. # if defined(CPPCHECK)
  1374. hdrdos.padding[0] = 0; /* to prevent "field unused" warnings */
  1375. hdr386.exe_format_level = 0;
  1376. hdr386.os = 0;
  1377. hdr386.padding1[0] = 0;
  1378. hdr386.padding2[0] = 0;
  1379. seg.pagemap = 0;
  1380. seg.mapsize = 0;
  1381. seg.reserved = 0;
  1382. # endif
  1383. if (DosGetInfoBlocks(&ptib, &ppib) != NO_ERROR) {
  1384. ABORT("DosGetInfoBlocks failed");
  1385. }
  1386. module_handle = ppib -> pib_hmte;
  1387. if (DosQueryModuleName(module_handle, PBUFSIZ, path) != NO_ERROR) {
  1388. ABORT("DosQueryModuleName failed");
  1389. }
  1390. myexefile = fopen(path, "rb");
  1391. if (myexefile == 0) {
  1392. ABORT_ARG1("Failed to open executable", ": %s", path);
  1393. }
  1394. if (fread((char *)(&hdrdos), 1, sizeof(hdrdos), myexefile)
  1395. < sizeof(hdrdos)) {
  1396. ABORT_ARG1("Could not read MSDOS header", " from: %s", path);
  1397. }
  1398. if (E_MAGIC(hdrdos) != EMAGIC) {
  1399. ABORT_ARG1("Bad DOS magic number", " in file: %s", path);
  1400. }
  1401. if (fseek(myexefile, E_LFANEW(hdrdos), SEEK_SET) != 0) {
  1402. ABORT_ARG1("Bad DOS magic number", " in file: %s", path);
  1403. }
  1404. if (fread((char *)(&hdr386), 1, sizeof(hdr386), myexefile)
  1405. < sizeof(hdr386)) {
  1406. ABORT_ARG1("Could not read OS/2 header", " from: %s", path);
  1407. }
  1408. if (E32_MAGIC1(hdr386) != E32MAGIC1 || E32_MAGIC2(hdr386) != E32MAGIC2) {
  1409. ABORT_ARG1("Bad OS/2 magic number", " in file: %s", path);
  1410. }
  1411. if (E32_BORDER(hdr386) != E32LEBO || E32_WORDER(hdr386) != E32LEWO) {
  1412. ABORT_ARG1("Bad byte order in executable", " file: %s", path);
  1413. }
  1414. if (E32_CPU(hdr386) == E32CPU286) {
  1415. ABORT_ARG1("GC cannot handle 80286 executables", ": %s", path);
  1416. }
  1417. if (fseek(myexefile, E_LFANEW(hdrdos) + E32_OBJTAB(hdr386),
  1418. SEEK_SET) != 0) {
  1419. ABORT_ARG1("Seek to object table failed", " in file: %s", path);
  1420. }
  1421. for (nsegs = E32_OBJCNT(hdr386); nsegs > 0; nsegs--) {
  1422. int flags;
  1423. if (fread((char *)(&seg), 1, sizeof(seg), myexefile) < sizeof(seg)) {
  1424. ABORT_ARG1("Could not read obj table entry", " from file: %s", path);
  1425. }
  1426. flags = O32_FLAGS(seg);
  1427. if (!(flags & OBJWRITE)) continue;
  1428. if (!(flags & OBJREAD)) continue;
  1429. if (flags & OBJINVALID) {
  1430. GC_err_printf("Object with invalid pages?\n");
  1431. continue;
  1432. }
  1433. GC_add_roots_inner((ptr_t)O32_BASE(seg),
  1434. (ptr_t)(O32_BASE(seg)+O32_SIZE(seg)), FALSE);
  1435. }
  1436. (void)fclose(myexefile);
  1437. }
  1438. # else /* !OS2 */
  1439. # if defined(GWW_VDB)
  1440. # ifndef MEM_WRITE_WATCH
  1441. # define MEM_WRITE_WATCH 0x200000
  1442. # endif
  1443. # ifndef WRITE_WATCH_FLAG_RESET
  1444. # define WRITE_WATCH_FLAG_RESET 1
  1445. # endif
  1446. /* Since we can't easily check whether ULONG_PTR and SIZE_T are */
  1447. /* defined in Win32 basetsd.h, we define own ULONG_PTR. */
  1448. # define GC_ULONG_PTR word
  1449. typedef UINT (WINAPI * GetWriteWatch_type)(
  1450. DWORD, PVOID, GC_ULONG_PTR /* SIZE_T */,
  1451. PVOID *, GC_ULONG_PTR *, PULONG);
  1452. static GetWriteWatch_type GetWriteWatch_func;
  1453. static DWORD GetWriteWatch_alloc_flag;
  1454. # define GC_GWW_AVAILABLE() (GetWriteWatch_func != NULL)
  1455. static void detect_GetWriteWatch(void)
  1456. {
  1457. static GC_bool done;
  1458. HMODULE hK32;
  1459. if (done)
  1460. return;
  1461. # if defined(MPROTECT_VDB)
  1462. {
  1463. char * str = GETENV("GC_USE_GETWRITEWATCH");
  1464. # if defined(GC_PREFER_MPROTECT_VDB)
  1465. if (str == NULL || (*str == '0' && *(str + 1) == '\0')) {
  1466. /* GC_USE_GETWRITEWATCH is unset or set to "0". */
  1467. done = TRUE; /* falling back to MPROTECT_VDB strategy. */
  1468. /* This should work as if GWW_VDB is undefined. */
  1469. return;
  1470. }
  1471. # else
  1472. if (str != NULL && *str == '0' && *(str + 1) == '\0') {
  1473. /* GC_USE_GETWRITEWATCH is set "0". */
  1474. done = TRUE; /* falling back to MPROTECT_VDB strategy. */
  1475. return;
  1476. }
  1477. # endif
  1478. }
  1479. # endif
  1480. # ifdef MSWINRT_FLAVOR
  1481. {
  1482. MEMORY_BASIC_INFORMATION memInfo;
  1483. SIZE_T result = VirtualQuery(GetProcAddress,
  1484. &memInfo, sizeof(memInfo));
  1485. if (result != sizeof(memInfo))
  1486. ABORT("Weird VirtualQuery result");
  1487. hK32 = (HMODULE)memInfo.AllocationBase;
  1488. }
  1489. # else
  1490. hK32 = GetModuleHandle(TEXT("kernel32.dll"));
  1491. # endif
  1492. if (hK32 != (HMODULE)0 &&
  1493. (GetWriteWatch_func = (GetWriteWatch_type)GetProcAddress(hK32,
  1494. "GetWriteWatch")) != NULL) {
  1495. /* Also check whether VirtualAlloc accepts MEM_WRITE_WATCH, */
  1496. /* as some versions of kernel32.dll have one but not the */
  1497. /* other, making the feature completely broken. */
  1498. void * page = VirtualAlloc(NULL, GC_page_size,
  1499. MEM_WRITE_WATCH | MEM_RESERVE,
  1500. PAGE_READWRITE);
  1501. if (page != NULL) {
  1502. PVOID pages[16];
  1503. GC_ULONG_PTR count = 16;
  1504. DWORD page_size;
  1505. /* Check that it actually works. In spite of some */
  1506. /* documentation it actually seems to exist on W2K. */
  1507. /* This test may be unnecessary, but ... */
  1508. if (GetWriteWatch_func(WRITE_WATCH_FLAG_RESET,
  1509. page, GC_page_size,
  1510. pages,
  1511. &count,
  1512. &page_size) != 0) {
  1513. /* GetWriteWatch always fails. */
  1514. GetWriteWatch_func = NULL;
  1515. } else {
  1516. GetWriteWatch_alloc_flag = MEM_WRITE_WATCH;
  1517. }
  1518. VirtualFree(page, 0 /* dwSize */, MEM_RELEASE);
  1519. } else {
  1520. /* GetWriteWatch will be useless. */
  1521. GetWriteWatch_func = NULL;
  1522. }
  1523. }
  1524. # ifndef SMALL_CONFIG
  1525. if (GetWriteWatch_func == NULL) {
  1526. GC_COND_LOG_PRINTF("Did not find a usable GetWriteWatch()\n");
  1527. } else {
  1528. GC_COND_LOG_PRINTF("Using GetWriteWatch()\n");
  1529. }
  1530. # endif
  1531. done = TRUE;
  1532. }
  1533. # else
  1534. # define GetWriteWatch_alloc_flag 0
  1535. # endif /* !GWW_VDB */
  1536. # if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32)
  1537. # ifdef MSWIN32
  1538. /* Unfortunately, we have to handle win32s very differently from NT, */
  1539. /* Since VirtualQuery has very different semantics. In particular, */
  1540. /* under win32s a VirtualQuery call on an unmapped page returns an */
  1541. /* invalid result. Under NT, GC_register_data_segments is a no-op */
  1542. /* and all real work is done by GC_register_dynamic_libraries. Under */
  1543. /* win32s, we cannot find the data segments associated with dll's. */
  1544. /* We register the main data segment here. */
  1545. GC_INNER GC_bool GC_no_win32_dlls = FALSE;
  1546. /* This used to be set for gcc, to avoid dealing with */
  1547. /* the structured exception handling issues. But we now have */
  1548. /* assembly code to do that right. */
  1549. GC_INNER GC_bool GC_wnt = FALSE;
  1550. /* This is a Windows NT derivative, i.e. NT, W2K, XP or later. */
  1551. GC_INNER void GC_init_win32(void)
  1552. {
  1553. # if defined(_WIN64) || (defined(_MSC_VER) && _MSC_VER >= 1800)
  1554. /* MS Visual Studio 2013 deprecates GetVersion, but on the other */
  1555. /* hand it cannot be used to target pre-Win2K. */
  1556. GC_wnt = TRUE;
  1557. # else
  1558. /* Set GC_wnt. If we're running under win32s, assume that no */
  1559. /* DLLs will be loaded. I doubt anyone still runs win32s, but... */
  1560. DWORD v = GetVersion();
  1561. GC_wnt = !(v & 0x80000000);
  1562. GC_no_win32_dlls |= ((!GC_wnt) && (v & 0xff) <= 3);
  1563. # endif
  1564. # ifdef USE_MUNMAP
  1565. if (GC_no_win32_dlls) {
  1566. /* Turn off unmapping for safety (since may not work well with */
  1567. /* GlobalAlloc). */
  1568. GC_unmap_threshold = 0;
  1569. }
  1570. # endif
  1571. }
  1572. /* Return the smallest address a such that VirtualQuery */
  1573. /* returns correct results for all addresses between a and start. */
  1574. /* Assumes VirtualQuery returns correct information for start. */
  1575. STATIC ptr_t GC_least_described_address(ptr_t start)
  1576. {
  1577. MEMORY_BASIC_INFORMATION buf;
  1578. LPVOID limit;
  1579. ptr_t p;
  1580. limit = GC_sysinfo.lpMinimumApplicationAddress;
  1581. p = (ptr_t)((word)start & ~(GC_page_size - 1));
  1582. for (;;) {
  1583. size_t result;
  1584. LPVOID q = (LPVOID)(p - GC_page_size);
  1585. if ((word)q > (word)p /* underflow */ || (word)q < (word)limit) break;
  1586. result = VirtualQuery(q, &buf, sizeof(buf));
  1587. if (result != sizeof(buf) || buf.AllocationBase == 0) break;
  1588. p = (ptr_t)(buf.AllocationBase);
  1589. }
  1590. return p;
  1591. }
  1592. # endif /* MSWIN32 */
  1593. # ifndef REDIRECT_MALLOC
  1594. /* We maintain a linked list of AllocationBase values that we know */
  1595. /* correspond to malloc heap sections. Currently this is only called */
  1596. /* during a GC. But there is some hope that for long running */
  1597. /* programs we will eventually see most heap sections. */
  1598. /* In the long run, it would be more reliable to occasionally walk */
  1599. /* the malloc heap with HeapWalk on the default heap. But that */
  1600. /* apparently works only for NT-based Windows. */
  1601. STATIC size_t GC_max_root_size = 100000; /* Appr. largest root size. */
  1602. # ifdef USE_WINALLOC
  1603. /* In the long run, a better data structure would also be nice ... */
  1604. STATIC struct GC_malloc_heap_list {
  1605. void * allocation_base;
  1606. struct GC_malloc_heap_list *next;
  1607. } *GC_malloc_heap_l = 0;
  1608. /* Is p the base of one of the malloc heap sections we already know */
  1609. /* about? */
  1610. STATIC GC_bool GC_is_malloc_heap_base(void *p)
  1611. {
  1612. struct GC_malloc_heap_list *q = GC_malloc_heap_l;
  1613. while (0 != q) {
  1614. if (q -> allocation_base == p) return TRUE;
  1615. q = q -> next;
  1616. }
  1617. return FALSE;
  1618. }
  1619. STATIC void *GC_get_allocation_base(void *p)
  1620. {
  1621. MEMORY_BASIC_INFORMATION buf;
  1622. size_t result = VirtualQuery(p, &buf, sizeof(buf));
  1623. if (result != sizeof(buf)) {
  1624. ABORT("Weird VirtualQuery result");
  1625. }
  1626. return buf.AllocationBase;
  1627. }
  1628. GC_INNER void GC_add_current_malloc_heap(void)
  1629. {
  1630. struct GC_malloc_heap_list *new_l =
  1631. malloc(sizeof(struct GC_malloc_heap_list));
  1632. void * candidate = GC_get_allocation_base(new_l);
  1633. if (new_l == 0) return;
  1634. if (GC_is_malloc_heap_base(candidate)) {
  1635. /* Try a little harder to find malloc heap. */
  1636. size_t req_size = 10000;
  1637. do {
  1638. void *p = malloc(req_size);
  1639. if (0 == p) {
  1640. free(new_l);
  1641. return;
  1642. }
  1643. candidate = GC_get_allocation_base(p);
  1644. free(p);
  1645. req_size *= 2;
  1646. } while (GC_is_malloc_heap_base(candidate)
  1647. && req_size < GC_max_root_size/10 && req_size < 500000);
  1648. if (GC_is_malloc_heap_base(candidate)) {
  1649. free(new_l);
  1650. return;
  1651. }
  1652. }
  1653. GC_COND_LOG_PRINTF("Found new system malloc AllocationBase at %p\n",
  1654. candidate);
  1655. new_l -> allocation_base = candidate;
  1656. new_l -> next = GC_malloc_heap_l;
  1657. GC_malloc_heap_l = new_l;
  1658. }
  1659. # endif /* USE_WINALLOC */
  1660. # endif /* !REDIRECT_MALLOC */
  1661. STATIC word GC_n_heap_bases = 0; /* See GC_heap_bases. */
  1662. /* Is p the start of either the malloc heap, or of one of our */
  1663. /* heap sections? */
  1664. GC_INNER GC_bool GC_is_heap_base(void *p)
  1665. {
  1666. unsigned i;
  1667. # ifndef REDIRECT_MALLOC
  1668. if (GC_root_size > GC_max_root_size) GC_max_root_size = GC_root_size;
  1669. # ifdef USE_WINALLOC
  1670. if (GC_is_malloc_heap_base(p)) return TRUE;
  1671. # endif
  1672. # endif
  1673. for (i = 0; i < GC_n_heap_bases; i++) {
  1674. if (GC_heap_bases[i] == p) return TRUE;
  1675. }
  1676. return FALSE;
  1677. }
  1678. #ifdef MSWIN32
  1679. STATIC void GC_register_root_section(ptr_t static_root)
  1680. {
  1681. MEMORY_BASIC_INFORMATION buf;
  1682. LPVOID p;
  1683. char * base;
  1684. char * limit;
  1685. if (!GC_no_win32_dlls) return;
  1686. p = base = limit = GC_least_described_address(static_root);
  1687. while ((word)p < (word)GC_sysinfo.lpMaximumApplicationAddress) {
  1688. size_t result = VirtualQuery(p, &buf, sizeof(buf));
  1689. char * new_limit;
  1690. DWORD protect;
  1691. if (result != sizeof(buf) || buf.AllocationBase == 0
  1692. || GC_is_heap_base(buf.AllocationBase)) break;
  1693. new_limit = (char *)p + buf.RegionSize;
  1694. protect = buf.Protect;
  1695. if (buf.State == MEM_COMMIT
  1696. && is_writable(protect)) {
  1697. if ((char *)p == limit) {
  1698. limit = new_limit;
  1699. } else {
  1700. if (base != limit) GC_add_roots_inner(base, limit, FALSE);
  1701. base = (char *)p;
  1702. limit = new_limit;
  1703. }
  1704. }
  1705. if ((word)p > (word)new_limit /* overflow */) break;
  1706. p = (LPVOID)new_limit;
  1707. }
  1708. if (base != limit) GC_add_roots_inner(base, limit, FALSE);
  1709. }
  1710. #endif /* MSWIN32 */
  1711. void GC_register_data_segments(void)
  1712. {
  1713. # ifdef MSWIN32
  1714. GC_register_root_section((ptr_t)&GC_pages_executable);
  1715. /* any other GC global variable would fit too. */
  1716. # endif
  1717. }
  1718. # else /* !OS2 && !Windows */
  1719. # if (defined(SVR4) || defined(AIX) || defined(DGUX) \
  1720. || (defined(LINUX) && defined(SPARC))) && !defined(PCR)
  1721. ptr_t GC_SysVGetDataStart(size_t max_page_size, ptr_t etext_addr)
  1722. {
  1723. word text_end = ((word)(etext_addr) + sizeof(word) - 1)
  1724. & ~(word)(sizeof(word) - 1);
  1725. /* etext rounded to word boundary */
  1726. word next_page = ((text_end + (word)max_page_size - 1)
  1727. & ~((word)max_page_size - 1));
  1728. word page_offset = (text_end & ((word)max_page_size - 1));
  1729. char * volatile result = (char *)(next_page + page_offset);
  1730. /* Note that this isn't equivalent to just adding */
  1731. /* max_page_size to &etext if &etext is at a page boundary */
  1732. GC_setup_temporary_fault_handler();
  1733. if (SETJMP(GC_jmp_buf) == 0) {
  1734. /* Try writing to the address. */
  1735. # ifdef AO_HAVE_fetch_and_add
  1736. volatile AO_t zero = 0;
  1737. (void)AO_fetch_and_add((volatile AO_t *)result, zero);
  1738. # else
  1739. /* Fallback to non-atomic fetch-and-store. */
  1740. char v = *result;
  1741. # if defined(CPPCHECK)
  1742. GC_noop1((word)&v);
  1743. # endif
  1744. *result = v;
  1745. # endif
  1746. GC_reset_fault_handler();
  1747. } else {
  1748. GC_reset_fault_handler();
  1749. /* We got here via a longjmp. The address is not readable. */
  1750. /* This is known to happen under Solaris 2.4 + gcc, which place */
  1751. /* string constants in the text segment, but after etext. */
  1752. /* Use plan B. Note that we now know there is a gap between */
  1753. /* text and data segments, so plan A brought us something. */
  1754. result = (char *)GC_find_limit(DATAEND, FALSE);
  1755. }
  1756. return((ptr_t)result);
  1757. }
  1758. # endif
  1759. #ifdef DATASTART_USES_BSDGETDATASTART
  1760. /* Its unclear whether this should be identical to the above, or */
  1761. /* whether it should apply to non-X86 architectures. */
  1762. /* For now we don't assume that there is always an empty page after */
  1763. /* etext. But in some cases there actually seems to be slightly more. */
  1764. /* This also deals with holes between read-only data and writable data. */
  1765. GC_INNER ptr_t GC_FreeBSDGetDataStart(size_t max_page_size,
  1766. ptr_t etext_addr)
  1767. {
  1768. word text_end = ((word)(etext_addr) + sizeof(word) - 1)
  1769. & ~(word)(sizeof(word) - 1);
  1770. /* etext rounded to word boundary */
  1771. volatile word next_page = (text_end + (word)max_page_size - 1)
  1772. & ~((word)max_page_size - 1);
  1773. volatile ptr_t result = (ptr_t)text_end;
  1774. GC_setup_temporary_fault_handler();
  1775. if (SETJMP(GC_jmp_buf) == 0) {
  1776. /* Try reading at the address. */
  1777. /* This should happen before there is another thread. */
  1778. for (; next_page < (word)DATAEND; next_page += (word)max_page_size)
  1779. *(volatile char *)next_page;
  1780. GC_reset_fault_handler();
  1781. } else {
  1782. GC_reset_fault_handler();
  1783. /* As above, we go to plan B */
  1784. result = GC_find_limit(DATAEND, FALSE);
  1785. }
  1786. return(result);
  1787. }
  1788. #endif /* DATASTART_USES_BSDGETDATASTART */
  1789. #ifdef AMIGA
  1790. # define GC_AMIGA_DS
  1791. # include "extra/AmigaOS.c"
  1792. # undef GC_AMIGA_DS
  1793. #elif defined(OPENBSD)
  1794. /* Depending on arch alignment, there can be multiple holes */
  1795. /* between DATASTART and DATAEND. Scan in DATASTART .. DATAEND */
  1796. /* and register each region. */
  1797. void GC_register_data_segments(void)
  1798. {
  1799. ptr_t region_start = DATASTART;
  1800. if ((word)region_start - 1U >= (word)DATAEND)
  1801. ABORT_ARG2("Wrong DATASTART/END pair",
  1802. ": %p .. %p", (void *)region_start, (void *)DATAEND);
  1803. for (;;) {
  1804. ptr_t region_end = GC_find_limit_openbsd(region_start, DATAEND);
  1805. GC_add_roots_inner(region_start, region_end, FALSE);
  1806. if ((word)region_end >= (word)DATAEND)
  1807. break;
  1808. region_start = GC_skip_hole_openbsd(region_end, DATAEND);
  1809. }
  1810. }
  1811. # else /* !OS2 && !Windows && !AMIGA && !OPENBSD */
  1812. # if !defined(PCR) && !defined(MACOS) && defined(REDIRECT_MALLOC) \
  1813. && defined(GC_SOLARIS_THREADS)
  1814. EXTERN_C_BEGIN
  1815. extern caddr_t sbrk(int);
  1816. EXTERN_C_END
  1817. # endif
  1818. void GC_register_data_segments(void)
  1819. {
  1820. # if !defined(PCR) && !defined(MACOS)
  1821. # if defined(REDIRECT_MALLOC) && defined(GC_SOLARIS_THREADS)
  1822. /* As of Solaris 2.3, the Solaris threads implementation */
  1823. /* allocates the data structure for the initial thread with */
  1824. /* sbrk at process startup. It needs to be scanned, so that */
  1825. /* we don't lose some malloc allocated data structures */
  1826. /* hanging from it. We're on thin ice here ... */
  1827. GC_ASSERT(DATASTART);
  1828. {
  1829. ptr_t p = (ptr_t)sbrk(0);
  1830. if ((word)DATASTART < (word)p)
  1831. GC_add_roots_inner(DATASTART, p, FALSE);
  1832. }
  1833. # elif defined(GC_DONT_REGISTER_MAIN_STATIC_DATA)
  1834. /* avoid referencing DATASTART & DATAEND as they may be invalid */
  1835. # else
  1836. if ((word)DATASTART - 1U >= (word)DATAEND) {
  1837. /* Subtract one to check also for NULL */
  1838. /* without a compiler warning. */
  1839. ABORT_ARG2("Wrong DATASTART/END pair",
  1840. ": %p .. %p", (void *)DATASTART, (void *)DATAEND);
  1841. }
  1842. GC_add_roots_inner(DATASTART, DATAEND, FALSE);
  1843. # ifdef GC_HAVE_DATAREGION2
  1844. if ((word)DATASTART2 - 1U >= (word)DATAEND2)
  1845. ABORT_ARG2("Wrong DATASTART/END2 pair",
  1846. ": %p .. %p", (void *)DATASTART2, (void *)DATAEND2);
  1847. GC_add_roots_inner(DATASTART2, DATAEND2, FALSE);
  1848. # endif
  1849. # endif
  1850. # endif
  1851. # if defined(MACOS)
  1852. {
  1853. # if defined(THINK_C)
  1854. extern void* GC_MacGetDataStart(void);
  1855. /* globals begin above stack and end at a5. */
  1856. GC_add_roots_inner((ptr_t)GC_MacGetDataStart(),
  1857. (ptr_t)LMGetCurrentA5(), FALSE);
  1858. # else
  1859. # if defined(__MWERKS__)
  1860. # if !__POWERPC__
  1861. extern void* GC_MacGetDataStart(void);
  1862. /* MATTHEW: Function to handle Far Globals (CW Pro 3) */
  1863. # if __option(far_data)
  1864. extern void* GC_MacGetDataEnd(void);
  1865. # endif
  1866. /* globals begin above stack and end at a5. */
  1867. GC_add_roots_inner((ptr_t)GC_MacGetDataStart(),
  1868. (ptr_t)LMGetCurrentA5(), FALSE);
  1869. /* MATTHEW: Handle Far Globals */
  1870. # if __option(far_data)
  1871. /* Far globals follow he QD globals: */
  1872. GC_add_roots_inner((ptr_t)LMGetCurrentA5(),
  1873. (ptr_t)GC_MacGetDataEnd(), FALSE);
  1874. # endif
  1875. # else
  1876. extern char __data_start__[], __data_end__[];
  1877. GC_add_roots_inner((ptr_t)&__data_start__,
  1878. (ptr_t)&__data_end__, FALSE);
  1879. # endif /* __POWERPC__ */
  1880. # endif /* __MWERKS__ */
  1881. # endif /* !THINK_C */
  1882. }
  1883. # endif /* MACOS */
  1884. /* Dynamic libraries are added at every collection, since they may */
  1885. /* change. */
  1886. }
  1887. # endif /* !AMIGA */
  1888. # endif /* !MSWIN32 && !MSWINCE */
  1889. # endif /* !OS2 */
  1890. /*
  1891. * Auxiliary routines for obtaining memory from OS.
  1892. */
  1893. # if !defined(OS2) && !defined(PCR) && !defined(AMIGA) \
  1894. && !defined(USE_WINALLOC) && !defined(MACOS) && !defined(DOS4GW) \
  1895. && !defined(NINTENDO_SWITCH) && !defined(NONSTOP) \
  1896. && !defined(SN_TARGET_ORBIS) && !defined(SN_TARGET_PS3) \
  1897. && !defined(SN_TARGET_PSP2) && !defined(RTEMS) && !defined(__CC_ARM)
  1898. # define SBRK_ARG_T ptrdiff_t
  1899. #if defined(MMAP_SUPPORTED)
  1900. #ifdef USE_MMAP_FIXED
  1901. # define GC_MMAP_FLAGS MAP_FIXED | MAP_PRIVATE
  1902. /* Seems to yield better performance on Solaris 2, but can */
  1903. /* be unreliable if something is already mapped at the address. */
  1904. #else
  1905. # define GC_MMAP_FLAGS MAP_PRIVATE
  1906. #endif
  1907. #ifdef USE_MMAP_ANON
  1908. # define zero_fd -1
  1909. # if defined(MAP_ANONYMOUS) && !defined(CPPCHECK)
  1910. # define OPT_MAP_ANON MAP_ANONYMOUS
  1911. # else
  1912. # define OPT_MAP_ANON MAP_ANON
  1913. # endif
  1914. #else
  1915. static int zero_fd = -1;
  1916. # define OPT_MAP_ANON 0
  1917. #endif
  1918. # ifndef MSWIN_XBOX1
  1919. # if defined(SYMBIAN) && !defined(USE_MMAP_ANON)
  1920. EXTERN_C_BEGIN
  1921. extern char *GC_get_private_path_and_zero_file(void);
  1922. EXTERN_C_END
  1923. # endif
  1924. STATIC ptr_t GC_unix_mmap_get_mem(size_t bytes)
  1925. {
  1926. void *result;
  1927. static ptr_t last_addr = HEAP_START;
  1928. # ifndef USE_MMAP_ANON
  1929. static GC_bool initialized = FALSE;
  1930. if (!EXPECT(initialized, TRUE)) {
  1931. # ifdef SYMBIAN
  1932. char *path = GC_get_private_path_and_zero_file();
  1933. if (path != NULL) {
  1934. zero_fd = open(path, O_RDWR | O_CREAT, 0666);
  1935. free(path);
  1936. }
  1937. # else
  1938. zero_fd = open("/dev/zero", O_RDONLY);
  1939. # endif
  1940. if (zero_fd == -1)
  1941. ABORT("Could not open /dev/zero");
  1942. if (fcntl(zero_fd, F_SETFD, FD_CLOEXEC) == -1)
  1943. WARN("Could not set FD_CLOEXEC for /dev/zero\n", 0);
  1944. initialized = TRUE;
  1945. }
  1946. # endif
  1947. if (bytes & (GC_page_size - 1)) ABORT("Bad GET_MEM arg");
  1948. result = mmap(last_addr, bytes, (PROT_READ | PROT_WRITE)
  1949. | (GC_pages_executable ? PROT_EXEC : 0),
  1950. GC_MMAP_FLAGS | OPT_MAP_ANON, zero_fd, 0/* offset */);
  1951. # undef IGNORE_PAGES_EXECUTABLE
  1952. if (result == MAP_FAILED) return(0);
  1953. last_addr = (ptr_t)(((word)result + bytes + GC_page_size - 1)
  1954. & ~(GC_page_size - 1));
  1955. # if !defined(LINUX)
  1956. if (last_addr == 0) {
  1957. /* Oops. We got the end of the address space. This isn't */
  1958. /* usable by arbitrary C code, since one-past-end pointers */
  1959. /* don't work, so we discard it and try again. */
  1960. munmap(result, ~GC_page_size - (size_t)result + 1);
  1961. /* Leave last page mapped, so we can't repeat. */
  1962. return GC_unix_mmap_get_mem(bytes);
  1963. }
  1964. # else
  1965. GC_ASSERT(last_addr != 0);
  1966. # endif
  1967. if (((word)result % HBLKSIZE) != 0)
  1968. ABORT(
  1969. "GC_unix_get_mem: Memory returned by mmap is not aligned to HBLKSIZE.");
  1970. return((ptr_t)result);
  1971. }
  1972. # endif /* !MSWIN_XBOX1 */
  1973. #endif /* MMAP_SUPPORTED */
  1974. #if defined(USE_MMAP)
  1975. ptr_t GC_unix_get_mem(size_t bytes)
  1976. {
  1977. return GC_unix_mmap_get_mem(bytes);
  1978. }
  1979. #else /* !USE_MMAP */
  1980. STATIC ptr_t GC_unix_sbrk_get_mem(size_t bytes)
  1981. {
  1982. ptr_t result;
  1983. # ifdef IRIX5
  1984. /* Bare sbrk isn't thread safe. Play by malloc rules. */
  1985. /* The equivalent may be needed on other systems as well. */
  1986. __LOCK_MALLOC();
  1987. # endif
  1988. {
  1989. ptr_t cur_brk = (ptr_t)sbrk(0);
  1990. SBRK_ARG_T lsbs = (word)cur_brk & (GC_page_size-1);
  1991. if ((SBRK_ARG_T)bytes < 0) {
  1992. result = 0; /* too big */
  1993. goto out;
  1994. }
  1995. if (lsbs != 0) {
  1996. if((ptr_t)sbrk((SBRK_ARG_T)GC_page_size - lsbs) == (ptr_t)(-1)) {
  1997. result = 0;
  1998. goto out;
  1999. }
  2000. }
  2001. # ifdef ADD_HEAP_GUARD_PAGES
  2002. /* This is useful for catching severe memory overwrite problems that */
  2003. /* span heap sections. It shouldn't otherwise be turned on. */
  2004. {
  2005. ptr_t guard = (ptr_t)sbrk((SBRK_ARG_T)GC_page_size);
  2006. if (mprotect(guard, GC_page_size, PROT_NONE) != 0)
  2007. ABORT("ADD_HEAP_GUARD_PAGES: mprotect failed");
  2008. }
  2009. # endif /* ADD_HEAP_GUARD_PAGES */
  2010. result = (ptr_t)sbrk((SBRK_ARG_T)bytes);
  2011. if (result == (ptr_t)(-1)) result = 0;
  2012. }
  2013. out:
  2014. # ifdef IRIX5
  2015. __UNLOCK_MALLOC();
  2016. # endif
  2017. return(result);
  2018. }
  2019. ptr_t GC_unix_get_mem(size_t bytes)
  2020. {
  2021. # if defined(MMAP_SUPPORTED)
  2022. /* By default, we try both sbrk and mmap, in that order. */
  2023. static GC_bool sbrk_failed = FALSE;
  2024. ptr_t result = 0;
  2025. if (!sbrk_failed) result = GC_unix_sbrk_get_mem(bytes);
  2026. if (0 == result) {
  2027. sbrk_failed = TRUE;
  2028. result = GC_unix_mmap_get_mem(bytes);
  2029. }
  2030. if (0 == result) {
  2031. /* Try sbrk again, in case sbrk memory became available. */
  2032. result = GC_unix_sbrk_get_mem(bytes);
  2033. }
  2034. return result;
  2035. # else /* !MMAP_SUPPORTED */
  2036. return GC_unix_sbrk_get_mem(bytes);
  2037. # endif
  2038. }
  2039. #endif /* !USE_MMAP */
  2040. # endif /* UN*X */
  2041. # ifdef OS2
  2042. void * os2_alloc(size_t bytes)
  2043. {
  2044. void * result;
  2045. if (DosAllocMem(&result, bytes, (PAG_READ | PAG_WRITE | PAG_COMMIT)
  2046. | (GC_pages_executable ? PAG_EXECUTE : 0))
  2047. != NO_ERROR) {
  2048. return(0);
  2049. }
  2050. /* FIXME: What's the purpose of this recursion? (Probably, if */
  2051. /* DosAllocMem returns memory at 0 address then just retry once.) */
  2052. if (result == 0) return(os2_alloc(bytes));
  2053. return(result);
  2054. }
  2055. # endif /* OS2 */
  2056. # ifdef MSWIN_XBOX1
  2057. void *durango_get_mem(size_t bytes, size_t page_size)
  2058. {
  2059. if (0 == bytes) return NULL;
  2060. return VirtualAlloc(NULL, bytes, MEM_COMMIT | MEM_TOP_DOWN,
  2061. PAGE_READWRITE);
  2062. }
  2063. #endif
  2064. #ifdef MSWINCE
  2065. ptr_t GC_wince_get_mem(size_t bytes)
  2066. {
  2067. ptr_t result = 0; /* initialized to prevent warning. */
  2068. word i;
  2069. bytes = ROUNDUP_PAGESIZE(bytes);
  2070. /* Try to find reserved, uncommitted pages */
  2071. for (i = 0; i < GC_n_heap_bases; i++) {
  2072. if (((word)(-(signed_word)GC_heap_lengths[i])
  2073. & (GC_sysinfo.dwAllocationGranularity-1))
  2074. >= bytes) {
  2075. result = GC_heap_bases[i] + GC_heap_lengths[i];
  2076. break;
  2077. }
  2078. }
  2079. if (i == GC_n_heap_bases) {
  2080. /* Reserve more pages */
  2081. size_t res_bytes =
  2082. SIZET_SAT_ADD(bytes, (size_t)GC_sysinfo.dwAllocationGranularity-1)
  2083. & ~((size_t)GC_sysinfo.dwAllocationGranularity-1);
  2084. /* If we ever support MPROTECT_VDB here, we will probably need to */
  2085. /* ensure that res_bytes is strictly > bytes, so that VirtualProtect */
  2086. /* never spans regions. It seems to be OK for a VirtualFree */
  2087. /* argument to span regions, so we should be OK for now. */
  2088. result = (ptr_t) VirtualAlloc(NULL, res_bytes,
  2089. MEM_RESERVE | MEM_TOP_DOWN,
  2090. GC_pages_executable ? PAGE_EXECUTE_READWRITE :
  2091. PAGE_READWRITE);
  2092. if (HBLKDISPL(result) != 0) ABORT("Bad VirtualAlloc result");
  2093. /* If I read the documentation correctly, this can */
  2094. /* only happen if HBLKSIZE > 64k or not a power of 2. */
  2095. if (GC_n_heap_bases >= MAX_HEAP_SECTS) ABORT("Too many heap sections");
  2096. if (result == NULL) return NULL;
  2097. GC_heap_bases[GC_n_heap_bases] = result;
  2098. GC_heap_lengths[GC_n_heap_bases] = 0;
  2099. GC_n_heap_bases++;
  2100. }
  2101. /* Commit pages */
  2102. result = (ptr_t) VirtualAlloc(result, bytes, MEM_COMMIT,
  2103. GC_pages_executable ? PAGE_EXECUTE_READWRITE :
  2104. PAGE_READWRITE);
  2105. # undef IGNORE_PAGES_EXECUTABLE
  2106. if (result != NULL) {
  2107. if (HBLKDISPL(result) != 0) ABORT("Bad VirtualAlloc result");
  2108. GC_heap_lengths[i] += bytes;
  2109. }
  2110. return(result);
  2111. }
  2112. #elif (defined(USE_WINALLOC) && !defined(MSWIN_XBOX1)) || defined(CYGWIN32)
  2113. # ifdef USE_GLOBAL_ALLOC
  2114. # define GLOBAL_ALLOC_TEST 1
  2115. # else
  2116. # define GLOBAL_ALLOC_TEST GC_no_win32_dlls
  2117. # endif
  2118. # if (defined(GC_USE_MEM_TOP_DOWN) && defined(USE_WINALLOC)) \
  2119. || defined(CPPCHECK)
  2120. DWORD GC_mem_top_down = MEM_TOP_DOWN;
  2121. /* Use GC_USE_MEM_TOP_DOWN for better 64-bit */
  2122. /* testing. Otherwise all addresses tend to */
  2123. /* end up in first 4GB, hiding bugs. */
  2124. # else
  2125. # define GC_mem_top_down 0
  2126. # endif /* !GC_USE_MEM_TOP_DOWN */
  2127. ptr_t GC_win32_get_mem(size_t bytes)
  2128. {
  2129. ptr_t result;
  2130. # ifndef USE_WINALLOC
  2131. result = GC_unix_get_mem(bytes);
  2132. # else
  2133. # if defined(MSWIN32) && !defined(MSWINRT_FLAVOR)
  2134. if (GLOBAL_ALLOC_TEST) {
  2135. /* VirtualAlloc doesn't like PAGE_EXECUTE_READWRITE. */
  2136. /* There are also unconfirmed rumors of other */
  2137. /* problems, so we dodge the issue. */
  2138. result = (ptr_t)GlobalAlloc(0, SIZET_SAT_ADD(bytes, HBLKSIZE));
  2139. /* Align it at HBLKSIZE boundary. */
  2140. result = (ptr_t)(((word)result + HBLKSIZE - 1)
  2141. & ~(word)(HBLKSIZE - 1));
  2142. } else
  2143. # endif
  2144. /* else */ {
  2145. /* VirtualProtect only works on regions returned by a */
  2146. /* single VirtualAlloc call. Thus we allocate one */
  2147. /* extra page, which will prevent merging of blocks */
  2148. /* in separate regions, and eliminate any temptation */
  2149. /* to call VirtualProtect on a range spanning regions. */
  2150. /* This wastes a small amount of memory, and risks */
  2151. /* increased fragmentation. But better alternatives */
  2152. /* would require effort. */
  2153. # ifdef MPROTECT_VDB
  2154. /* We can't check for GC_incremental here (because */
  2155. /* GC_enable_incremental() might be called some time */
  2156. /* later after the GC initialization). */
  2157. # ifdef GWW_VDB
  2158. # define VIRTUAL_ALLOC_PAD (GC_GWW_AVAILABLE() ? 0 : 1)
  2159. # else
  2160. # define VIRTUAL_ALLOC_PAD 1
  2161. # endif
  2162. # else
  2163. # define VIRTUAL_ALLOC_PAD 0
  2164. # endif
  2165. /* Pass the MEM_WRITE_WATCH only if GetWriteWatch-based */
  2166. /* VDBs are enabled and the GetWriteWatch function is */
  2167. /* available. Otherwise we waste resources or possibly */
  2168. /* cause VirtualAlloc to fail (observed in Windows 2000 */
  2169. /* SP2). */
  2170. result = (ptr_t) VirtualAlloc(NULL,
  2171. SIZET_SAT_ADD(bytes, VIRTUAL_ALLOC_PAD),
  2172. GetWriteWatch_alloc_flag
  2173. | (MEM_COMMIT | MEM_RESERVE)
  2174. | GC_mem_top_down,
  2175. GC_pages_executable ? PAGE_EXECUTE_READWRITE :
  2176. PAGE_READWRITE);
  2177. # undef IGNORE_PAGES_EXECUTABLE
  2178. }
  2179. # endif /* USE_WINALLOC */
  2180. if (HBLKDISPL(result) != 0) ABORT("Bad VirtualAlloc result");
  2181. /* If I read the documentation correctly, this can */
  2182. /* only happen if HBLKSIZE > 64k or not a power of 2. */
  2183. if (GC_n_heap_bases >= MAX_HEAP_SECTS) ABORT("Too many heap sections");
  2184. if (0 != result) GC_heap_bases[GC_n_heap_bases++] = result;
  2185. return(result);
  2186. }
  2187. GC_API void GC_CALL GC_win32_free_heap(void)
  2188. {
  2189. # ifndef MSWINRT_FLAVOR
  2190. # ifndef CYGWIN32
  2191. if (GLOBAL_ALLOC_TEST)
  2192. # endif
  2193. {
  2194. while (GC_n_heap_bases-- > 0) {
  2195. # ifdef CYGWIN32
  2196. /* FIXME: Is it OK to use non-GC free() here? */
  2197. # else
  2198. GlobalFree(GC_heap_bases[GC_n_heap_bases]);
  2199. # endif
  2200. GC_heap_bases[GC_n_heap_bases] = 0;
  2201. }
  2202. return;
  2203. }
  2204. # endif
  2205. # ifndef CYGWIN32
  2206. /* Avoiding VirtualAlloc leak. */
  2207. while (GC_n_heap_bases > 0) {
  2208. VirtualFree(GC_heap_bases[--GC_n_heap_bases], 0, MEM_RELEASE);
  2209. GC_heap_bases[GC_n_heap_bases] = 0;
  2210. }
  2211. # endif
  2212. }
  2213. #endif /* USE_WINALLOC || CYGWIN32 */
  2214. #ifdef AMIGA
  2215. # define GC_AMIGA_AM
  2216. # include "extra/AmigaOS.c"
  2217. # undef GC_AMIGA_AM
  2218. #endif
  2219. #if defined(HAIKU)
  2220. # include <stdlib.h>
  2221. ptr_t GC_haiku_get_mem(size_t bytes)
  2222. {
  2223. void* mem;
  2224. GC_ASSERT(GC_page_size != 0);
  2225. if (posix_memalign(&mem, GC_page_size, bytes) == 0)
  2226. return mem;
  2227. return NULL;
  2228. }
  2229. #endif /* HAIKU */
  2230. #ifdef USE_MUNMAP
  2231. /* For now, this only works on Win32/WinCE and some Unix-like */
  2232. /* systems. If you have something else, don't define */
  2233. /* USE_MUNMAP. */
  2234. #if !defined(NN_PLATFORM_CTR) && !defined(MSWIN32) && !defined(MSWINCE) \
  2235. && !defined(MSWIN_XBOX1)
  2236. # include <unistd.h>
  2237. # ifdef SN_TARGET_PS3
  2238. # include <sys/memory.h>
  2239. # else
  2240. # include <sys/mman.h>
  2241. # endif
  2242. # include <sys/stat.h>
  2243. # include <sys/types.h>
  2244. #endif
  2245. /* Compute a page aligned starting address for the unmap */
  2246. /* operation on a block of size bytes starting at start. */
  2247. /* Return 0 if the block is too small to make this feasible. */
  2248. STATIC ptr_t GC_unmap_start(ptr_t start, size_t bytes)
  2249. {
  2250. ptr_t result = (ptr_t)(((word)start + GC_page_size - 1)
  2251. & ~(GC_page_size - 1));
  2252. if ((word)(result + GC_page_size) > (word)(start + bytes)) return 0;
  2253. return result;
  2254. }
  2255. /* Compute end address for an unmap operation on the indicated */
  2256. /* block. */
  2257. STATIC ptr_t GC_unmap_end(ptr_t start, size_t bytes)
  2258. {
  2259. return (ptr_t)((word)(start + bytes) & ~(GC_page_size - 1));
  2260. }
  2261. /* Under Win32/WinCE we commit (map) and decommit (unmap) */
  2262. /* memory using VirtualAlloc and VirtualFree. These functions */
  2263. /* work on individual allocations of virtual memory, made */
  2264. /* previously using VirtualAlloc with the MEM_RESERVE flag. */
  2265. /* The ranges we need to (de)commit may span several of these */
  2266. /* allocations; therefore we use VirtualQuery to check */
  2267. /* allocation lengths, and split up the range as necessary. */
  2268. /* We assume that GC_remap is called on exactly the same range */
  2269. /* as a previous call to GC_unmap. It is safe to consistently */
  2270. /* round the endpoints in both places. */
  2271. GC_INNER void GC_unmap(ptr_t start, size_t bytes)
  2272. {
  2273. ptr_t start_addr = GC_unmap_start(start, bytes);
  2274. ptr_t end_addr = GC_unmap_end(start, bytes);
  2275. word len = end_addr - start_addr;
  2276. if (0 == start_addr) return;
  2277. # ifdef USE_WINALLOC
  2278. while (len != 0) {
  2279. MEMORY_BASIC_INFORMATION mem_info;
  2280. word free_len;
  2281. if (VirtualQuery(start_addr, &mem_info, sizeof(mem_info))
  2282. != sizeof(mem_info))
  2283. ABORT("Weird VirtualQuery result");
  2284. free_len = (len < mem_info.RegionSize) ? len : mem_info.RegionSize;
  2285. if (!VirtualFree(start_addr, free_len, MEM_DECOMMIT))
  2286. ABORT("VirtualFree failed");
  2287. GC_unmapped_bytes += free_len;
  2288. start_addr += free_len;
  2289. len -= free_len;
  2290. }
  2291. # elif defined(SN_TARGET_PS3)
  2292. ps3_free_mem(start_addr, len);
  2293. # else
  2294. /* We immediately remap it to prevent an intervening mmap from */
  2295. /* accidentally grabbing the same address space. */
  2296. {
  2297. # if defined(CYGWIN32) || defined(LINUX)
  2298. /* Calling mmap() with the new protection flags on an */
  2299. /* existing memory map with MAP_FIXED is broken on Cygwin. */
  2300. /* However, calling mprotect() on the given address range */
  2301. /* with PROT_NONE seems to work fine. */
  2302. /* On Linux, low RLIMIT_AS value may lead to mmap failure. */
  2303. # if defined(LINUX) && !defined(FORCE_MPROTECT_BEFORE_MADVISE)
  2304. /* On Linux, at least, madvise() should be sufficient. */
  2305. # else
  2306. if (mprotect(start_addr, len, PROT_NONE))
  2307. ABORT("mprotect(PROT_NONE) failed");
  2308. # endif
  2309. # if !defined(CYGWIN32)
  2310. /* On Linux (and some other platforms probably), */
  2311. /* mprotect(PROT_NONE) is just disabling access to */
  2312. /* the pages but not returning them to OS. */
  2313. if (madvise(start_addr, len, MADV_DONTNEED) == -1)
  2314. ABORT_ARG3("unmap: madvise failed",
  2315. " at %p (length %lu), errcode= %d",
  2316. (void *)start_addr, (unsigned long)len, errno);
  2317. # endif
  2318. # else
  2319. void * result = mmap(start_addr, len, PROT_NONE,
  2320. MAP_PRIVATE | MAP_FIXED | OPT_MAP_ANON,
  2321. zero_fd, 0/* offset */);
  2322. if (result != (void *)start_addr)
  2323. ABORT("mmap(PROT_NONE) failed");
  2324. # if defined(CPPCHECK) || defined(LINT2)
  2325. /* Explicitly store the resource handle to a global variable. */
  2326. GC_noop1((word)result);
  2327. # endif
  2328. # endif /* !CYGWIN32 */
  2329. }
  2330. GC_unmapped_bytes += len;
  2331. # endif
  2332. }
  2333. GC_INNER void GC_remap(ptr_t start, size_t bytes)
  2334. {
  2335. ptr_t start_addr = GC_unmap_start(start, bytes);
  2336. ptr_t end_addr = GC_unmap_end(start, bytes);
  2337. word len = end_addr - start_addr;
  2338. if (0 == start_addr) return;
  2339. /* FIXME: Handle out-of-memory correctly (at least for Win32) */
  2340. # ifdef USE_WINALLOC
  2341. while (len != 0) {
  2342. MEMORY_BASIC_INFORMATION mem_info;
  2343. word alloc_len;
  2344. ptr_t result;
  2345. if (VirtualQuery(start_addr, &mem_info, sizeof(mem_info))
  2346. != sizeof(mem_info))
  2347. ABORT("Weird VirtualQuery result");
  2348. alloc_len = (len < mem_info.RegionSize) ? len : mem_info.RegionSize;
  2349. result = VirtualAlloc(start_addr, alloc_len, MEM_COMMIT,
  2350. GC_pages_executable ? PAGE_EXECUTE_READWRITE :
  2351. PAGE_READWRITE);
  2352. if (result != start_addr) {
  2353. if (GetLastError() == ERROR_NOT_ENOUGH_MEMORY ||
  2354. GetLastError() == ERROR_OUTOFMEMORY) {
  2355. ABORT("Not enough memory to process remapping");
  2356. } else {
  2357. ABORT("VirtualAlloc remapping failed");
  2358. }
  2359. }
  2360. # ifdef LINT2
  2361. GC_noop1((word)result);
  2362. # endif
  2363. GC_unmapped_bytes -= alloc_len;
  2364. start_addr += alloc_len;
  2365. len -= alloc_len;
  2366. }
  2367. # undef IGNORE_PAGES_EXECUTABLE
  2368. # else
  2369. /* It was already remapped with PROT_NONE. */
  2370. {
  2371. # if !defined(FORCE_MPROTECT_BEFORE_MADVISE) && defined(LINUX) && !defined(PREFER_MMAP_PROT_NONE)
  2372. /* Nothing to unprotect as madvise() is just a hint. */
  2373. # elif defined(NACL)
  2374. /* NaCl does not expose mprotect, but mmap should work fine. */
  2375. void *result = mmap(start_addr, len, (PROT_READ | PROT_WRITE)
  2376. | (GC_pages_executable ? PROT_EXEC : 0),
  2377. MAP_PRIVATE | MAP_FIXED | OPT_MAP_ANON,
  2378. zero_fd, 0 /* offset */);
  2379. if (result != (void *)start_addr)
  2380. ABORT("mmap as mprotect failed");
  2381. # if defined(CPPCHECK) || defined(LINT2)
  2382. GC_noop1((word)result);
  2383. # endif
  2384. # undef IGNORE_PAGES_EXECUTABLE
  2385. # else
  2386. if (mprotect(start_addr, len, (PROT_READ | PROT_WRITE)
  2387. | (GC_pages_executable ? PROT_EXEC : 0)) != 0) {
  2388. ABORT_ARG3("mprotect remapping failed",
  2389. " at %p (length %lu), errcode= %d",
  2390. (void *)start_addr, (unsigned long)len, errno);
  2391. }
  2392. # undef IGNORE_PAGES_EXECUTABLE
  2393. # endif /* !NACL */
  2394. }
  2395. GC_unmapped_bytes -= len;
  2396. # endif
  2397. }
  2398. /* Two adjacent blocks have already been unmapped and are about to */
  2399. /* be merged. Unmap the whole block. This typically requires */
  2400. /* that we unmap a small section in the middle that was not previously */
  2401. /* unmapped due to alignment constraints. */
  2402. GC_INNER void GC_unmap_gap(ptr_t start1, size_t bytes1, ptr_t start2,
  2403. size_t bytes2)
  2404. {
  2405. ptr_t start1_addr = GC_unmap_start(start1, bytes1);
  2406. ptr_t end1_addr = GC_unmap_end(start1, bytes1);
  2407. ptr_t start2_addr = GC_unmap_start(start2, bytes2);
  2408. ptr_t start_addr = end1_addr;
  2409. ptr_t end_addr = start2_addr;
  2410. size_t len;
  2411. GC_ASSERT(start1 + bytes1 == start2);
  2412. if (0 == start1_addr) start_addr = GC_unmap_start(start1, bytes1 + bytes2);
  2413. if (0 == start2_addr) end_addr = GC_unmap_end(start1, bytes1 + bytes2);
  2414. if (0 == start_addr) return;
  2415. len = end_addr - start_addr;
  2416. # ifdef USE_WINALLOC
  2417. while (len != 0) {
  2418. MEMORY_BASIC_INFORMATION mem_info;
  2419. word free_len;
  2420. if (VirtualQuery(start_addr, &mem_info, sizeof(mem_info))
  2421. != sizeof(mem_info))
  2422. ABORT("Weird VirtualQuery result");
  2423. free_len = (len < mem_info.RegionSize) ? len : mem_info.RegionSize;
  2424. if (!VirtualFree(start_addr, free_len, MEM_DECOMMIT))
  2425. ABORT("VirtualFree failed");
  2426. GC_unmapped_bytes += free_len;
  2427. start_addr += free_len;
  2428. len -= free_len;
  2429. }
  2430. # else
  2431. if (len != 0) {
  2432. /* Immediately remap as above. */
  2433. # if defined(CYGWIN32) || defined(LINUX)
  2434. # if defined(LINUX) && !defined(FORCE_MPROTECT_BEFORE_MADVISE)
  2435. /* On Linux, at least, madvise() should be sufficient. */
  2436. # else
  2437. if (mprotect(start_addr, len, PROT_NONE))
  2438. ABORT("mprotect(PROT_NONE) failed");
  2439. # endif
  2440. # if !defined(CYGWIN32)
  2441. /* On Linux (and some other platforms probably), */
  2442. /* mprotect(PROT_NONE) is just disabling access to */
  2443. /* the pages but not returning them to OS. */
  2444. if (madvise(start_addr, len, MADV_DONTNEED) == -1)
  2445. ABORT_ARG3("unmap_gap: madvise failed",
  2446. " at %p (length %lu), errcode= %d",
  2447. (void *)start_addr, (unsigned long)len, errno);
  2448. # endif
  2449. # else
  2450. void * result = mmap(start_addr, len, PROT_NONE,
  2451. MAP_PRIVATE | MAP_FIXED | OPT_MAP_ANON,
  2452. zero_fd, 0/* offset */);
  2453. if (result != (void *)start_addr)
  2454. ABORT("mmap(PROT_NONE) failed");
  2455. # if defined(CPPCHECK) || defined(LINT2)
  2456. GC_noop1((word)result);
  2457. # endif
  2458. # endif /* !CYGWIN32 */
  2459. GC_unmapped_bytes += len;
  2460. }
  2461. # endif
  2462. }
  2463. #endif /* USE_MUNMAP */
  2464. /* Routine for pushing any additional roots. In THREADS */
  2465. /* environment, this is also responsible for marking from */
  2466. /* thread stacks. */
  2467. #ifndef THREADS
  2468. GC_push_other_roots_proc GC_push_other_roots = 0;
  2469. #else /* THREADS */
  2470. # ifdef PCR
  2471. PCR_ERes GC_push_thread_stack(PCR_Th_T *t, PCR_Any dummy)
  2472. {
  2473. struct PCR_ThCtl_TInfoRep info;
  2474. PCR_ERes result;
  2475. info.ti_stkLow = info.ti_stkHi = 0;
  2476. result = PCR_ThCtl_GetInfo(t, &info);
  2477. GC_push_all_stack((ptr_t)(info.ti_stkLow), (ptr_t)(info.ti_stkHi));
  2478. return(result);
  2479. }
  2480. /* Push the contents of an old object. We treat this as stack */
  2481. /* data only because that makes it robust against mark stack */
  2482. /* overflow. */
  2483. PCR_ERes GC_push_old_obj(void *p, size_t size, PCR_Any data)
  2484. {
  2485. GC_push_all_stack((ptr_t)p, (ptr_t)p + size);
  2486. return(PCR_ERes_okay);
  2487. }
  2488. extern struct PCR_MM_ProcsRep * GC_old_allocator;
  2489. /* defined in pcr_interface.c. */
  2490. STATIC void GC_CALLBACK GC_default_push_other_roots(void)
  2491. {
  2492. /* Traverse data allocated by previous memory managers. */
  2493. if ((*(GC_old_allocator->mmp_enumerate))(PCR_Bool_false,
  2494. GC_push_old_obj, 0)
  2495. != PCR_ERes_okay) {
  2496. ABORT("Old object enumeration failed");
  2497. }
  2498. /* Traverse all thread stacks. */
  2499. if (PCR_ERes_IsErr(
  2500. PCR_ThCtl_ApplyToAllOtherThreads(GC_push_thread_stack,0))
  2501. || PCR_ERes_IsErr(GC_push_thread_stack(PCR_Th_CurrThread(), 0))) {
  2502. ABORT("Thread stack marking failed");
  2503. }
  2504. }
  2505. # endif /* PCR */
  2506. # if defined(NN_PLATFORM_CTR) || defined(NINTENDO_SWITCH) \
  2507. || defined(GC_PTHREADS) || defined(GC_WIN32_THREADS)
  2508. STATIC void GC_CALLBACK GC_default_push_other_roots(void)
  2509. {
  2510. GC_push_all_stacks();
  2511. }
  2512. # endif
  2513. # ifdef SN_TARGET_PS3
  2514. STATIC void GC_CALLBACK GC_default_push_other_roots(void)
  2515. {
  2516. ABORT("GC_default_push_other_roots is not implemented");
  2517. }
  2518. void GC_push_thread_structures(void)
  2519. {
  2520. ABORT("GC_push_thread_structures is not implemented");
  2521. }
  2522. # endif /* SN_TARGET_PS3 */
  2523. GC_push_other_roots_proc GC_push_other_roots = GC_default_push_other_roots;
  2524. #endif /* THREADS */
  2525. GC_API void GC_CALL GC_set_push_other_roots(GC_push_other_roots_proc fn)
  2526. {
  2527. GC_push_other_roots = fn;
  2528. }
  2529. GC_API GC_push_other_roots_proc GC_CALL GC_get_push_other_roots(void)
  2530. {
  2531. return GC_push_other_roots;
  2532. }
  2533. void GC_reset_default_push_other_roots(void)
  2534. {
  2535. #ifdef THREADS
  2536. GC_push_other_roots = GC_default_push_other_roots;
  2537. #else
  2538. GC_push_other_roots = 0;
  2539. #endif
  2540. }
  2541. GC_mark_stack_empty_proc GC_on_mark_stack_empty;
  2542. GC_API void GC_CALL GC_set_mark_stack_empty (GC_mark_stack_empty_proc fn)
  2543. {
  2544. GC_on_mark_stack_empty = fn;
  2545. }
  2546. GC_API GC_mark_stack_empty_proc GC_CALL GC_get_mark_stack_empty (void)
  2547. {
  2548. return GC_on_mark_stack_empty;
  2549. }
  2550. /*
  2551. * Routines for accessing dirty bits on virtual pages.
  2552. * There are six ways to maintain this information:
  2553. * DEFAULT_VDB: A simple dummy implementation that treats every page
  2554. * as possibly dirty. This makes incremental collection
  2555. * useless, but the implementation is still correct.
  2556. * MANUAL_VDB: Stacks and static data are always considered dirty.
  2557. * Heap pages are considered dirty if GC_dirty(p) has been
  2558. * called on some pointer p pointing to somewhere inside
  2559. * an object on that page. A GC_dirty() call on a large
  2560. * object directly dirties only a single page, but for
  2561. * MANUAL_VDB we are careful to treat an object with a dirty
  2562. * page as completely dirty.
  2563. * In order to avoid races, an object must be marked dirty
  2564. * after it is written, and a reference to the object
  2565. * must be kept on a stack or in a register in the interim.
  2566. * With threads enabled, an object directly reachable from the
  2567. * stack at the time of a collection is treated as dirty.
  2568. * In single-threaded mode, it suffices to ensure that no
  2569. * collection can take place between the pointer assignment
  2570. * and the GC_dirty() call.
  2571. * PCR_VDB: Use PPCRs virtual dirty bit facility.
  2572. * PROC_VDB: Use the /proc facility for reading dirty bits. Only
  2573. * works under some SVR4 variants. Even then, it may be
  2574. * too slow to be entirely satisfactory. Requires reading
  2575. * dirty bits for entire address space. Implementations tend
  2576. * to assume that the client is a (slow) debugger.
  2577. * MPROTECT_VDB:Protect pages and then catch the faults to keep track of
  2578. * dirtied pages. The implementation (and implementability)
  2579. * is highly system dependent. This usually fails when system
  2580. * calls write to a protected page. We prevent the read system
  2581. * call from doing so. It is the clients responsibility to
  2582. * make sure that other system calls are similarly protected
  2583. * or write only to the stack.
  2584. * GWW_VDB: Use the Win32 GetWriteWatch functions, if available, to
  2585. * read dirty bits. In case it is not available (because we
  2586. * are running on Windows 95, Windows 2000 or earlier),
  2587. * MPROTECT_VDB may be defined as a fallback strategy.
  2588. */
  2589. #if defined(GWW_VDB) || defined(MPROTECT_VDB) || defined(PROC_VDB) \
  2590. || defined(MANUAL_VDB)
  2591. /* Is the HBLKSIZE sized page at h marked dirty in the local buffer? */
  2592. /* If the actual page size is different, this returns TRUE if any */
  2593. /* of the pages overlapping h are dirty. This routine may err on the */
  2594. /* side of labeling pages as dirty (and this implementation does). */
  2595. GC_INNER GC_bool GC_page_was_dirty(struct hblk * h)
  2596. {
  2597. word index;
  2598. if (HDR(h) == 0)
  2599. return TRUE;
  2600. index = PHT_HASH(h);
  2601. return get_pht_entry_from_index(GC_grungy_pages, index);
  2602. }
  2603. #endif
  2604. #if (defined(CHECKSUMS) && defined(GWW_VDB)) || defined(PROC_VDB)
  2605. /* Add all pages in pht2 to pht1. */
  2606. STATIC void GC_or_pages(page_hash_table pht1, page_hash_table pht2)
  2607. {
  2608. unsigned i;
  2609. for (i = 0; i < PHT_SIZE; i++) pht1[i] |= pht2[i];
  2610. }
  2611. /* Used only if GWW_VDB. */
  2612. # ifdef MPROTECT_VDB
  2613. STATIC GC_bool GC_gww_page_was_ever_dirty(struct hblk * h)
  2614. # else
  2615. GC_INNER GC_bool GC_page_was_ever_dirty(struct hblk * h)
  2616. # endif
  2617. {
  2618. word index;
  2619. if (HDR(h) == 0)
  2620. return TRUE;
  2621. index = PHT_HASH(h);
  2622. return get_pht_entry_from_index(GC_written_pages, index);
  2623. }
  2624. #endif /* CHECKSUMS && GWW_VDB || PROC_VDB */
  2625. #if ((defined(GWW_VDB) || defined(PROC_VDB)) && !defined(MPROTECT_VDB)) \
  2626. || defined(MANUAL_VDB) || defined(DEFAULT_VDB)
  2627. /* Ignore write hints. They don't help us here. */
  2628. GC_INNER void GC_remove_protection(struct hblk * h GC_ATTR_UNUSED,
  2629. word nblocks GC_ATTR_UNUSED,
  2630. GC_bool is_ptrfree GC_ATTR_UNUSED) {}
  2631. #endif
  2632. #ifdef GWW_VDB
  2633. # define GC_GWW_BUF_LEN (MAXHINCR * HBLKSIZE / 4096 /* X86 page size */)
  2634. /* Still susceptible to overflow, if there are very large allocations, */
  2635. /* and everything is dirty. */
  2636. static PVOID gww_buf[GC_GWW_BUF_LEN];
  2637. # ifndef MPROTECT_VDB
  2638. # define GC_gww_dirty_init GC_dirty_init
  2639. # endif
  2640. GC_INNER GC_bool GC_gww_dirty_init(void)
  2641. {
  2642. detect_GetWriteWatch();
  2643. return GC_GWW_AVAILABLE();
  2644. }
  2645. # ifdef MPROTECT_VDB
  2646. STATIC void GC_gww_read_dirty(GC_bool output_unneeded)
  2647. # else
  2648. GC_INNER void GC_read_dirty(GC_bool output_unneeded)
  2649. # endif
  2650. {
  2651. word i;
  2652. if (!output_unneeded)
  2653. BZERO(GC_grungy_pages, sizeof(GC_grungy_pages));
  2654. for (i = 0; i != GC_n_heap_sects; ++i) {
  2655. GC_ULONG_PTR count;
  2656. do {
  2657. PVOID * pages = gww_buf;
  2658. DWORD page_size;
  2659. count = GC_GWW_BUF_LEN;
  2660. /* GetWriteWatch is documented as returning non-zero when it */
  2661. /* fails, but the documentation doesn't explicitly say why it */
  2662. /* would fail or what its behaviour will be if it fails. */
  2663. /* It does appear to fail, at least on recent W2K instances, if */
  2664. /* the underlying memory was not allocated with the appropriate */
  2665. /* flag. This is common if GC_enable_incremental is called */
  2666. /* shortly after GC initialization. To avoid modifying the */
  2667. /* interface, we silently work around such a failure, it only */
  2668. /* affects the initial (small) heap allocation. If there are */
  2669. /* more dirty pages than will fit in the buffer, this is not */
  2670. /* treated as a failure; we must check the page count in the */
  2671. /* loop condition. Since each partial call will reset the */
  2672. /* status of some pages, this should eventually terminate even */
  2673. /* in the overflow case. */
  2674. if (GetWriteWatch_func(WRITE_WATCH_FLAG_RESET,
  2675. GC_heap_sects[i].hs_start,
  2676. GC_heap_sects[i].hs_bytes,
  2677. pages,
  2678. &count,
  2679. &page_size) != 0) {
  2680. static int warn_count = 0;
  2681. struct hblk * start = (struct hblk *)GC_heap_sects[i].hs_start;
  2682. static struct hblk *last_warned = 0;
  2683. size_t nblocks = divHBLKSZ(GC_heap_sects[i].hs_bytes);
  2684. if (i != 0 && last_warned != start && warn_count++ < 5) {
  2685. last_warned = start;
  2686. WARN("GC_gww_read_dirty unexpectedly failed at %p: "
  2687. "Falling back to marking all pages dirty\n", start);
  2688. }
  2689. if (!output_unneeded) {
  2690. unsigned j;
  2691. for (j = 0; j < nblocks; ++j) {
  2692. word hash = PHT_HASH(start + j);
  2693. set_pht_entry_from_index(GC_grungy_pages, hash);
  2694. }
  2695. }
  2696. count = 1; /* Done with this section. */
  2697. } else /* succeeded */ if (!output_unneeded) {
  2698. PVOID * pages_end = pages + count;
  2699. while (pages != pages_end) {
  2700. struct hblk * h = (struct hblk *) *pages++;
  2701. struct hblk * h_end = (struct hblk *) ((char *) h + page_size);
  2702. do {
  2703. set_pht_entry_from_index(GC_grungy_pages, PHT_HASH(h));
  2704. } while ((word)(++h) < (word)h_end);
  2705. }
  2706. }
  2707. } while (count == GC_GWW_BUF_LEN);
  2708. /* FIXME: It's unclear from Microsoft's documentation if this loop */
  2709. /* is useful. We suspect the call just fails if the buffer fills */
  2710. /* up. But that should still be handled correctly. */
  2711. }
  2712. # ifdef CHECKSUMS
  2713. GC_ASSERT(!output_unneeded);
  2714. GC_or_pages(GC_written_pages, GC_grungy_pages);
  2715. # endif
  2716. }
  2717. #endif /* GWW_VDB */
  2718. #ifdef DEFAULT_VDB
  2719. /* All of the following assume the allocation lock is held. */
  2720. /* The client asserts that unallocated pages in the heap are never */
  2721. /* written. */
  2722. /* Initialize virtual dirty bit implementation. */
  2723. GC_INNER GC_bool GC_dirty_init(void)
  2724. {
  2725. GC_VERBOSE_LOG_PRINTF("Initializing DEFAULT_VDB...\n");
  2726. return TRUE;
  2727. }
  2728. /* Retrieve system dirty bits for heap to a local buffer. */
  2729. /* Restore the systems notion of which pages are dirty. */
  2730. GC_INNER void GC_read_dirty(GC_bool output_unneeded GC_ATTR_UNUSED) {}
  2731. /* Is the HBLKSIZE sized page at h marked dirty in the local buffer? */
  2732. /* If the actual page size is different, this returns TRUE if any */
  2733. /* of the pages overlapping h are dirty. This routine may err on the */
  2734. /* side of labeling pages as dirty (and this implementation does). */
  2735. GC_INNER GC_bool GC_page_was_dirty(struct hblk * h GC_ATTR_UNUSED)
  2736. {
  2737. return(TRUE);
  2738. }
  2739. /* The following two routines are typically less crucial. */
  2740. /* They matter most with large dynamic libraries, or if we can't */
  2741. /* accurately identify stacks, e.g. under Solaris 2.X. Otherwise the */
  2742. /* following default versions are adequate. */
  2743. # ifdef CHECKSUMS
  2744. /* Could any valid GC heap pointer ever have been written to this page? */
  2745. GC_INNER GC_bool GC_page_was_ever_dirty(struct hblk * h GC_ATTR_UNUSED)
  2746. {
  2747. return(TRUE);
  2748. }
  2749. # endif /* CHECKSUMS */
  2750. #endif /* DEFAULT_VDB */
  2751. #ifdef MANUAL_VDB
  2752. /* Initialize virtual dirty bit implementation. */
  2753. GC_INNER GC_bool GC_dirty_init(void)
  2754. {
  2755. GC_VERBOSE_LOG_PRINTF("Initializing MANUAL_VDB...\n");
  2756. /* GC_dirty_pages and GC_grungy_pages are already cleared. */
  2757. return TRUE;
  2758. }
  2759. /* Retrieve system dirty bits for the heap to a local buffer */
  2760. /* (unless output_unneeded). Restore the systems notion of */
  2761. /* which pages are dirty. */
  2762. GC_INNER void GC_read_dirty(GC_bool output_unneeded)
  2763. {
  2764. if (!output_unneeded)
  2765. BCOPY((word *)GC_dirty_pages, GC_grungy_pages, sizeof(GC_dirty_pages));
  2766. BZERO((word *)GC_dirty_pages, (sizeof GC_dirty_pages));
  2767. }
  2768. #ifndef GC_DISABLE_INCREMENTAL
  2769. # ifndef THREADS
  2770. # define async_set_pht_entry_from_index(db, index) \
  2771. set_pht_entry_from_index(db, index)
  2772. # elif defined(set_pht_entry_from_index_concurrent)
  2773. # define async_set_pht_entry_from_index(db, index) \
  2774. set_pht_entry_from_index_concurrent(db, index)
  2775. # elif defined(AO_HAVE_test_and_set_acquire)
  2776. /* We need to lock around the bitmap update (in the write fault */
  2777. /* handler or GC_dirty) in order to avoid the risk of losing a bit. */
  2778. /* We do this with a test-and-set spin lock if possible. */
  2779. GC_INNER volatile AO_TS_t GC_fault_handler_lock = AO_TS_INITIALIZER;
  2780. static void async_set_pht_entry_from_index(volatile page_hash_table db,
  2781. size_t index)
  2782. {
  2783. GC_acquire_dirty_lock();
  2784. set_pht_entry_from_index(db, index);
  2785. GC_release_dirty_lock();
  2786. }
  2787. # else
  2788. # error No test_and_set operation: Introduces a race.
  2789. # endif /* THREADS && !AO_HAVE_test_and_set_acquire */
  2790. #else
  2791. # define async_set_pht_entry_from_index(db, index)
  2792. #endif /* !GC_DISABLE_INCREMENTAL */
  2793. /* Mark the page containing p as dirty. Logically, this dirties the */
  2794. /* entire object. */
  2795. #if !IL2CPP_ENABLE_WRITE_BARRIER_VALIDATION
  2796. GC_API void GC_dirty_inner(const void *p)
  2797. {
  2798. word index = PHT_HASH(p);
  2799. async_set_pht_entry_from_index(GC_dirty_pages, index);
  2800. }
  2801. #endif
  2802. # ifdef CHECKSUMS
  2803. /* Could any valid GC heap pointer ever have been written to this page? */
  2804. GC_INNER GC_bool GC_page_was_ever_dirty(struct hblk * h GC_ATTR_UNUSED)
  2805. {
  2806. /* FIXME - implement me. */
  2807. return(TRUE);
  2808. }
  2809. # endif /* CHECKSUMS */
  2810. #endif /* MANUAL_VDB */
  2811. #ifdef MPROTECT_VDB
  2812. /* See DEFAULT_VDB for interface descriptions. */
  2813. /*
  2814. * This implementation maintains dirty bits itself by catching write
  2815. * faults and keeping track of them. We assume nobody else catches
  2816. * SIGBUS or SIGSEGV. We assume no write faults occur in system calls.
  2817. * This means that clients must ensure that system calls don't write
  2818. * to the write-protected heap. Probably the best way to do this is to
  2819. * ensure that system calls write at most to pointer-free objects in the
  2820. * heap, and do even that only if we are on a platform on which those
  2821. * are not protected. Another alternative is to wrap system calls
  2822. * (see example for read below), but the current implementation holds
  2823. * applications.
  2824. * We assume the page size is a multiple of HBLKSIZE.
  2825. * We prefer them to be the same. We avoid protecting pointer-free
  2826. * objects only if they are the same.
  2827. */
  2828. # ifdef DARWIN
  2829. /* Using vm_protect (mach syscall) over mprotect (BSD syscall) seems to
  2830. decrease the likelihood of some of the problems described below. */
  2831. # include <mach/vm_map.h>
  2832. STATIC mach_port_t GC_task_self = 0;
  2833. # define PROTECT(addr,len) \
  2834. if (vm_protect(GC_task_self, (vm_address_t)(addr), (vm_size_t)(len), \
  2835. FALSE, VM_PROT_READ \
  2836. | (GC_pages_executable ? VM_PROT_EXECUTE : 0)) \
  2837. == KERN_SUCCESS) {} else ABORT("vm_protect(PROTECT) failed")
  2838. # define UNPROTECT(addr,len) \
  2839. if (vm_protect(GC_task_self, (vm_address_t)(addr), (vm_size_t)(len), \
  2840. FALSE, (VM_PROT_READ | VM_PROT_WRITE) \
  2841. | (GC_pages_executable ? VM_PROT_EXECUTE : 0)) \
  2842. == KERN_SUCCESS) {} else ABORT("vm_protect(UNPROTECT) failed")
  2843. # elif !defined(USE_WINALLOC)
  2844. # include <sys/mman.h>
  2845. # include <signal.h>
  2846. # if !defined(HAIKU)
  2847. # include <sys/syscall.h>
  2848. # endif
  2849. # define PROTECT(addr, len) \
  2850. if (mprotect((caddr_t)(addr), (size_t)(len), \
  2851. PROT_READ \
  2852. | (GC_pages_executable ? PROT_EXEC : 0)) >= 0) { \
  2853. } else ABORT("mprotect failed")
  2854. # define UNPROTECT(addr, len) \
  2855. if (mprotect((caddr_t)(addr), (size_t)(len), \
  2856. (PROT_READ | PROT_WRITE) \
  2857. | (GC_pages_executable ? PROT_EXEC : 0)) >= 0) { \
  2858. } else ABORT(GC_pages_executable ? \
  2859. "un-mprotect executable page failed" \
  2860. " (probably disabled by OS)" : \
  2861. "un-mprotect failed")
  2862. # undef IGNORE_PAGES_EXECUTABLE
  2863. # else /* USE_WINALLOC */
  2864. # ifndef MSWINCE
  2865. # include <signal.h>
  2866. # endif
  2867. static DWORD protect_junk;
  2868. # define PROTECT(addr, len) \
  2869. if (VirtualProtect((addr), (len), \
  2870. GC_pages_executable ? PAGE_EXECUTE_READ : \
  2871. PAGE_READONLY, \
  2872. &protect_junk)) { \
  2873. } else ABORT_ARG1("VirtualProtect failed", \
  2874. ": errcode= 0x%X", (unsigned)GetLastError())
  2875. # define UNPROTECT(addr, len) \
  2876. if (VirtualProtect((addr), (len), \
  2877. GC_pages_executable ? PAGE_EXECUTE_READWRITE : \
  2878. PAGE_READWRITE, \
  2879. &protect_junk)) { \
  2880. } else ABORT("un-VirtualProtect failed")
  2881. # endif /* USE_WINALLOC */
  2882. # if defined(MSWIN32)
  2883. typedef LPTOP_LEVEL_EXCEPTION_FILTER SIG_HNDLR_PTR;
  2884. # undef SIG_DFL
  2885. # define SIG_DFL (LPTOP_LEVEL_EXCEPTION_FILTER)((signed_word)-1)
  2886. # elif defined(MSWINCE)
  2887. typedef LONG (WINAPI *SIG_HNDLR_PTR)(struct _EXCEPTION_POINTERS *);
  2888. # undef SIG_DFL
  2889. # define SIG_DFL (SIG_HNDLR_PTR) (-1)
  2890. # elif defined(DARWIN)
  2891. typedef void (* SIG_HNDLR_PTR)();
  2892. # else
  2893. typedef void (* SIG_HNDLR_PTR)(int, siginfo_t *, void *);
  2894. typedef void (* PLAIN_HNDLR_PTR)(int);
  2895. # endif
  2896. # if defined(__GLIBC__)
  2897. # if __GLIBC__ < 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ < 2
  2898. # error glibc too old?
  2899. # endif
  2900. # endif
  2901. #ifndef DARWIN
  2902. STATIC SIG_HNDLR_PTR GC_old_segv_handler = 0;
  2903. /* Also old MSWIN32 ACCESS_VIOLATION filter */
  2904. # if !defined(MSWIN32) && !defined(MSWINCE)
  2905. STATIC SIG_HNDLR_PTR GC_old_bus_handler = 0;
  2906. # if defined(FREEBSD) || defined(HURD) || defined(HPUX)
  2907. STATIC GC_bool GC_old_bus_handler_used_si = FALSE;
  2908. # endif
  2909. STATIC GC_bool GC_old_segv_handler_used_si = FALSE;
  2910. # endif /* !MSWIN32 */
  2911. #endif /* !DARWIN */
  2912. #ifdef THREADS
  2913. /* This function is used only by the fault handler. Potential data */
  2914. /* race between this function and GC_install_header, GC_remove_header */
  2915. /* should not be harmful because the added or removed header should */
  2916. /* be already unprotected. */
  2917. GC_ATTR_NO_SANITIZE_THREAD
  2918. static GC_bool is_header_found_async(void *addr)
  2919. {
  2920. # ifdef HASH_TL
  2921. hdr *result;
  2922. GET_HDR((ptr_t)addr, result);
  2923. return result != NULL;
  2924. # else
  2925. return HDR_INNER(addr) != NULL;
  2926. # endif
  2927. }
  2928. #else
  2929. # define is_header_found_async(addr) (HDR(addr) != NULL)
  2930. #endif /* !THREADS */
  2931. #ifndef DARWIN
  2932. # if !defined(MSWIN32) && !defined(MSWINCE)
  2933. # include <errno.h>
  2934. # if defined(FREEBSD) || defined(HURD) || defined(HPUX)
  2935. # define SIG_OK (sig == SIGBUS || sig == SIGSEGV)
  2936. # else
  2937. # define SIG_OK (sig == SIGSEGV)
  2938. /* Catch SIGSEGV but ignore SIGBUS. */
  2939. # endif
  2940. # if defined(FREEBSD)
  2941. # ifndef SEGV_ACCERR
  2942. # define SEGV_ACCERR 2
  2943. # endif
  2944. # if defined(AARCH64) || defined(ARM32) || defined(MIPS)
  2945. # define CODE_OK (si -> si_code == SEGV_ACCERR)
  2946. # elif defined(POWERPC)
  2947. # define AIM /* Pretend that we're AIM. */
  2948. # include <machine/trap.h>
  2949. # define CODE_OK (si -> si_code == EXC_DSI \
  2950. || si -> si_code == SEGV_ACCERR)
  2951. # else
  2952. # define CODE_OK (si -> si_code == BUS_PAGE_FAULT \
  2953. || si -> si_code == SEGV_ACCERR)
  2954. # endif
  2955. # elif defined(OSF1)
  2956. # define CODE_OK (si -> si_code == 2 /* experimentally determined */)
  2957. # elif defined(IRIX5)
  2958. # define CODE_OK (si -> si_code == EACCES)
  2959. # elif defined(HAIKU) || defined(HURD)
  2960. # define CODE_OK TRUE
  2961. # elif defined(LINUX)
  2962. # define CODE_OK TRUE
  2963. /* Empirically c.trapno == 14, on IA32, but is that useful? */
  2964. /* Should probably consider alignment issues on other */
  2965. /* architectures. */
  2966. # elif defined(HPUX)
  2967. # define CODE_OK (si -> si_code == SEGV_ACCERR \
  2968. || si -> si_code == BUS_ADRERR \
  2969. || si -> si_code == BUS_UNKNOWN \
  2970. || si -> si_code == SEGV_UNKNOWN \
  2971. || si -> si_code == BUS_OBJERR)
  2972. # elif defined(SUNOS5SIGS)
  2973. # define CODE_OK (si -> si_code == SEGV_ACCERR)
  2974. # endif
  2975. # ifndef NO_GETCONTEXT
  2976. # include <ucontext.h>
  2977. # endif
  2978. STATIC void GC_write_fault_handler(int sig, siginfo_t *si, void *raw_sc)
  2979. # else
  2980. # define SIG_OK (exc_info -> ExceptionRecord -> ExceptionCode \
  2981. == STATUS_ACCESS_VIOLATION)
  2982. # define CODE_OK (exc_info -> ExceptionRecord -> ExceptionInformation[0] \
  2983. == 1) /* Write fault */
  2984. STATIC LONG WINAPI GC_write_fault_handler(
  2985. struct _EXCEPTION_POINTERS *exc_info)
  2986. # endif /* MSWIN32 || MSWINCE */
  2987. {
  2988. # if !defined(MSWIN32) && !defined(MSWINCE)
  2989. char *addr = (char *)si->si_addr;
  2990. # else
  2991. char * addr = (char *) (exc_info -> ExceptionRecord
  2992. -> ExceptionInformation[1]);
  2993. # endif
  2994. if (SIG_OK && CODE_OK) {
  2995. struct hblk * h = (struct hblk *)((word)addr & ~(GC_page_size-1));
  2996. GC_bool in_allocd_block;
  2997. size_t i;
  2998. # ifdef CHECKSUMS
  2999. GC_record_fault(h);
  3000. # endif
  3001. # ifdef SUNOS5SIGS
  3002. /* Address is only within the correct physical page. */
  3003. in_allocd_block = FALSE;
  3004. for (i = 0; i < divHBLKSZ(GC_page_size); i++) {
  3005. if (is_header_found_async(&h[i])) {
  3006. in_allocd_block = TRUE;
  3007. break;
  3008. }
  3009. }
  3010. # else
  3011. in_allocd_block = is_header_found_async(addr);
  3012. # endif
  3013. if (!in_allocd_block) {
  3014. /* FIXME - We should make sure that we invoke the */
  3015. /* old handler with the appropriate calling */
  3016. /* sequence, which often depends on SA_SIGINFO. */
  3017. /* Heap blocks now begin and end on page boundaries */
  3018. SIG_HNDLR_PTR old_handler;
  3019. # if defined(MSWIN32) || defined(MSWINCE)
  3020. old_handler = GC_old_segv_handler;
  3021. # else
  3022. GC_bool used_si;
  3023. # if defined(FREEBSD) || defined(HURD) || defined(HPUX)
  3024. if (sig == SIGBUS) {
  3025. old_handler = GC_old_bus_handler;
  3026. used_si = GC_old_bus_handler_used_si;
  3027. } else
  3028. # endif
  3029. /* else */ {
  3030. old_handler = GC_old_segv_handler;
  3031. used_si = GC_old_segv_handler_used_si;
  3032. }
  3033. # endif
  3034. if (old_handler == (SIG_HNDLR_PTR)SIG_DFL) {
  3035. # if !defined(MSWIN32) && !defined(MSWINCE)
  3036. ABORT_ARG1("Unexpected bus error or segmentation fault",
  3037. " at %p", (void *)addr);
  3038. # else
  3039. return(EXCEPTION_CONTINUE_SEARCH);
  3040. # endif
  3041. } else {
  3042. /*
  3043. * FIXME: This code should probably check if the
  3044. * old signal handler used the traditional style and
  3045. * if so call it using that style.
  3046. */
  3047. # if defined(MSWIN32) || defined(MSWINCE)
  3048. return((*old_handler)(exc_info));
  3049. # else
  3050. if (used_si)
  3051. ((SIG_HNDLR_PTR)old_handler) (sig, si, raw_sc);
  3052. else
  3053. /* FIXME: should pass nonstandard args as well. */
  3054. ((PLAIN_HNDLR_PTR)old_handler) (sig);
  3055. return;
  3056. # endif
  3057. }
  3058. }
  3059. UNPROTECT(h, GC_page_size);
  3060. /* We need to make sure that no collection occurs between */
  3061. /* the UNPROTECT and the setting of the dirty bit. Otherwise */
  3062. /* a write by a third thread might go unnoticed. Reversing */
  3063. /* the order is just as bad, since we would end up unprotecting */
  3064. /* a page in a GC cycle during which it's not marked. */
  3065. /* Currently we do this by disabling the thread stopping */
  3066. /* signals while this handler is running. An alternative might */
  3067. /* be to record the fact that we're about to unprotect, or */
  3068. /* have just unprotected a page in the GC's thread structure, */
  3069. /* and then to have the thread stopping code set the dirty */
  3070. /* flag, if necessary. */
  3071. for (i = 0; i < divHBLKSZ(GC_page_size); i++) {
  3072. word index = PHT_HASH(h+i);
  3073. async_set_pht_entry_from_index(GC_dirty_pages, index);
  3074. }
  3075. /* The write may not take place before dirty bits are read. */
  3076. /* But then we'll fault again ... */
  3077. # if defined(MSWIN32) || defined(MSWINCE)
  3078. return(EXCEPTION_CONTINUE_EXECUTION);
  3079. # else
  3080. return;
  3081. # endif
  3082. }
  3083. # if defined(MSWIN32) || defined(MSWINCE)
  3084. return EXCEPTION_CONTINUE_SEARCH;
  3085. # else
  3086. ABORT_ARG1("Unexpected bus error or segmentation fault",
  3087. " at %p", (void *)addr);
  3088. # endif
  3089. }
  3090. # ifdef GC_WIN32_THREADS
  3091. GC_INNER void GC_set_write_fault_handler(void)
  3092. {
  3093. SetUnhandledExceptionFilter(GC_write_fault_handler);
  3094. }
  3095. # endif
  3096. #endif /* !DARWIN */
  3097. /* We hold the allocation lock. We expect block h to be written */
  3098. /* shortly. Ensure that all pages containing any part of the n hblks */
  3099. /* starting at h are no longer protected. If is_ptrfree is false, also */
  3100. /* ensure that they will subsequently appear to be dirty. Not allowed */
  3101. /* to call GC_printf (and the friends) here, see Win32 GC_stop_world() */
  3102. /* for the information. */
  3103. GC_INNER void GC_remove_protection(struct hblk *h, word nblocks,
  3104. GC_bool is_ptrfree)
  3105. {
  3106. struct hblk * h_trunc; /* Truncated to page boundary */
  3107. struct hblk * h_end; /* Page boundary following block end */
  3108. struct hblk * current;
  3109. # if defined(GWW_VDB)
  3110. if (GC_GWW_AVAILABLE()) return;
  3111. # endif
  3112. if (!GC_incremental) return;
  3113. h_trunc = (struct hblk *)((word)h & ~(GC_page_size-1));
  3114. h_end = (struct hblk *)(((word)(h + nblocks) + GC_page_size - 1)
  3115. & ~(GC_page_size - 1));
  3116. if (h_end == h_trunc + 1 &&
  3117. get_pht_entry_from_index(GC_dirty_pages, PHT_HASH(h_trunc))) {
  3118. /* already marked dirty, and hence unprotected. */
  3119. return;
  3120. }
  3121. for (current = h_trunc; (word)current < (word)h_end; ++current) {
  3122. word index = PHT_HASH(current);
  3123. if (!is_ptrfree || (word)current < (word)h
  3124. || (word)current >= (word)(h + nblocks)) {
  3125. async_set_pht_entry_from_index(GC_dirty_pages, index);
  3126. }
  3127. }
  3128. UNPROTECT(h_trunc, (ptr_t)h_end - (ptr_t)h_trunc);
  3129. }
  3130. #ifdef USE_MUNMAP
  3131. /* MPROTECT_VDB cannot deal with address space holes (for now), */
  3132. /* so if the collector is configured with both MPROTECT_VDB and */
  3133. /* USE_MUNMAP then, as a work around, select only one of them */
  3134. /* during GC_init or GC_enable_incremental. */
  3135. GC_INNER GC_bool GC_dirty_init(void)
  3136. {
  3137. if (GC_unmap_threshold != 0) {
  3138. if (GETENV("GC_UNMAP_THRESHOLD") != NULL
  3139. || GETENV("GC_FORCE_UNMAP_ON_GCOLLECT") != NULL
  3140. || GC_has_unmapped_memory()) {
  3141. WARN("Can't maintain mprotect-based dirty bits"
  3142. " in case of unmapping\n", 0);
  3143. return FALSE;
  3144. }
  3145. GC_unmap_threshold = 0; /* in favor of incremental collection */
  3146. WARN("Memory unmapping is disabled as incompatible"
  3147. " with MPROTECT_VDB\n", 0);
  3148. }
  3149. return GC_mprotect_dirty_init();
  3150. }
  3151. #else
  3152. # define GC_mprotect_dirty_init GC_dirty_init
  3153. #endif /* !USE_MUNMAP */
  3154. #if !defined(DARWIN)
  3155. GC_INNER GC_bool GC_mprotect_dirty_init(void)
  3156. {
  3157. # if !defined(MSWIN32) && !defined(MSWINCE)
  3158. struct sigaction act, oldact;
  3159. act.sa_flags = SA_RESTART | SA_SIGINFO;
  3160. act.sa_sigaction = GC_write_fault_handler;
  3161. (void)sigemptyset(&act.sa_mask);
  3162. # if defined(THREADS) && !defined(GC_OPENBSD_UTHREADS) \
  3163. && !defined(GC_WIN32_THREADS) && !defined(NACL)
  3164. /* Arrange to postpone the signal while we are in a write fault */
  3165. /* handler. This effectively makes the handler atomic w.r.t. */
  3166. /* stopping the world for GC. */
  3167. (void)sigaddset(&act.sa_mask, GC_get_suspend_signal());
  3168. # endif
  3169. # endif /* !MSWIN32 */
  3170. GC_VERBOSE_LOG_PRINTF(
  3171. "Initializing mprotect virtual dirty bit implementation\n");
  3172. if (GC_page_size % HBLKSIZE != 0) {
  3173. ABORT("Page size not multiple of HBLKSIZE");
  3174. }
  3175. # if !defined(MSWIN32) && !defined(MSWINCE)
  3176. /* act.sa_restorer is deprecated and should not be initialized. */
  3177. # if defined(GC_IRIX_THREADS)
  3178. sigaction(SIGSEGV, 0, &oldact);
  3179. sigaction(SIGSEGV, &act, 0);
  3180. # else
  3181. {
  3182. int res = sigaction(SIGSEGV, &act, &oldact);
  3183. if (res != 0) ABORT("Sigaction failed");
  3184. }
  3185. # endif
  3186. if (oldact.sa_flags & SA_SIGINFO) {
  3187. GC_old_segv_handler = oldact.sa_sigaction;
  3188. GC_old_segv_handler_used_si = TRUE;
  3189. } else {
  3190. GC_old_segv_handler = (SIG_HNDLR_PTR)oldact.sa_handler;
  3191. GC_old_segv_handler_used_si = FALSE;
  3192. }
  3193. if (GC_old_segv_handler == (SIG_HNDLR_PTR)SIG_IGN) {
  3194. WARN("Previously ignored segmentation violation!?\n", 0);
  3195. GC_old_segv_handler = (SIG_HNDLR_PTR)SIG_DFL;
  3196. }
  3197. if (GC_old_segv_handler != (SIG_HNDLR_PTR)SIG_DFL) {
  3198. GC_VERBOSE_LOG_PRINTF("Replaced other SIGSEGV handler\n");
  3199. }
  3200. # if defined(HPUX) || defined(LINUX) || defined(HURD) \
  3201. || (defined(FREEBSD) && (defined(__GLIBC__) || defined(SUNOS5SIGS)))
  3202. sigaction(SIGBUS, &act, &oldact);
  3203. if ((oldact.sa_flags & SA_SIGINFO) != 0) {
  3204. GC_old_bus_handler = oldact.sa_sigaction;
  3205. # if !defined(LINUX)
  3206. GC_old_bus_handler_used_si = TRUE;
  3207. # endif
  3208. } else {
  3209. GC_old_bus_handler = (SIG_HNDLR_PTR)oldact.sa_handler;
  3210. # if !defined(LINUX)
  3211. GC_old_bus_handler_used_si = FALSE;
  3212. # endif
  3213. }
  3214. if (GC_old_bus_handler == (SIG_HNDLR_PTR)SIG_IGN) {
  3215. WARN("Previously ignored bus error!?\n", 0);
  3216. # if !defined(LINUX)
  3217. GC_old_bus_handler = (SIG_HNDLR_PTR)SIG_DFL;
  3218. # else
  3219. /* GC_old_bus_handler is not used by GC_write_fault_handler. */
  3220. # endif
  3221. } else if (GC_old_bus_handler != (SIG_HNDLR_PTR)SIG_DFL) {
  3222. GC_VERBOSE_LOG_PRINTF("Replaced other SIGBUS handler\n");
  3223. }
  3224. # endif /* HPUX || LINUX || HURD || (FREEBSD && SUNOS5SIGS) */
  3225. # endif /* ! MS windows */
  3226. # if defined(GWW_VDB)
  3227. if (GC_gww_dirty_init())
  3228. return TRUE;
  3229. # endif
  3230. # if defined(MSWIN32)
  3231. GC_old_segv_handler = SetUnhandledExceptionFilter(GC_write_fault_handler);
  3232. if (GC_old_segv_handler != NULL) {
  3233. GC_COND_LOG_PRINTF("Replaced other UnhandledExceptionFilter\n");
  3234. } else {
  3235. GC_old_segv_handler = SIG_DFL;
  3236. }
  3237. # elif defined(MSWINCE)
  3238. /* MPROTECT_VDB is unsupported for WinCE at present. */
  3239. /* FIXME: implement it (if possible). */
  3240. # endif
  3241. # if defined(CPPCHECK) && defined(ADDRESS_SANITIZER)
  3242. GC_noop1((word)&__asan_default_options);
  3243. # endif
  3244. return TRUE;
  3245. }
  3246. #endif /* !DARWIN */
  3247. GC_API int GC_CALL GC_incremental_protection_needs(void)
  3248. {
  3249. GC_ASSERT(GC_is_initialized);
  3250. if (GC_page_size == HBLKSIZE) {
  3251. return GC_PROTECTS_POINTER_HEAP;
  3252. } else {
  3253. return GC_PROTECTS_POINTER_HEAP | GC_PROTECTS_PTRFREE_HEAP;
  3254. }
  3255. }
  3256. #define HAVE_INCREMENTAL_PROTECTION_NEEDS
  3257. #define IS_PTRFREE(hhdr) ((hhdr)->hb_descr == 0)
  3258. #define PAGE_ALIGNED(x) !((word)(x) & (GC_page_size - 1))
  3259. STATIC void GC_protect_heap(void)
  3260. {
  3261. unsigned i;
  3262. GC_bool protect_all =
  3263. (0 != (GC_incremental_protection_needs() & GC_PROTECTS_PTRFREE_HEAP));
  3264. for (i = 0; i < GC_n_heap_sects; i++) {
  3265. ptr_t start = GC_heap_sects[i].hs_start;
  3266. size_t len = GC_heap_sects[i].hs_bytes;
  3267. if (protect_all) {
  3268. PROTECT(start, len);
  3269. } else {
  3270. struct hblk * current;
  3271. struct hblk * current_start; /* Start of block to be protected. */
  3272. struct hblk * limit;
  3273. GC_ASSERT(PAGE_ALIGNED(len));
  3274. GC_ASSERT(PAGE_ALIGNED(start));
  3275. current_start = current = (struct hblk *)start;
  3276. limit = (struct hblk *)(start + len);
  3277. while ((word)current < (word)limit) {
  3278. hdr * hhdr;
  3279. word nhblks;
  3280. GC_bool is_ptrfree;
  3281. GC_ASSERT(PAGE_ALIGNED(current));
  3282. GET_HDR(current, hhdr);
  3283. if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
  3284. /* This can happen only if we're at the beginning of a */
  3285. /* heap segment, and a block spans heap segments. */
  3286. /* We will handle that block as part of the preceding */
  3287. /* segment. */
  3288. GC_ASSERT(current_start == current);
  3289. current_start = ++current;
  3290. continue;
  3291. }
  3292. if (HBLK_IS_FREE(hhdr)) {
  3293. GC_ASSERT(PAGE_ALIGNED(hhdr -> hb_sz));
  3294. nhblks = divHBLKSZ(hhdr -> hb_sz);
  3295. is_ptrfree = TRUE; /* dirty on alloc */
  3296. } else {
  3297. nhblks = OBJ_SZ_TO_BLOCKS(hhdr -> hb_sz);
  3298. is_ptrfree = IS_PTRFREE(hhdr);
  3299. }
  3300. if (is_ptrfree) {
  3301. if ((word)current_start < (word)current) {
  3302. PROTECT(current_start, (ptr_t)current - (ptr_t)current_start);
  3303. }
  3304. current_start = (current += nhblks);
  3305. } else {
  3306. current += nhblks;
  3307. }
  3308. }
  3309. if ((word)current_start < (word)current) {
  3310. PROTECT(current_start, (ptr_t)current - (ptr_t)current_start);
  3311. }
  3312. }
  3313. }
  3314. }
  3315. /* We assume that either the world is stopped or its OK to lose dirty */
  3316. /* bits while this is happening (as in GC_enable_incremental). */
  3317. GC_INNER void GC_read_dirty(GC_bool output_unneeded)
  3318. {
  3319. # if defined(GWW_VDB)
  3320. if (GC_GWW_AVAILABLE()) {
  3321. GC_gww_read_dirty(output_unneeded);
  3322. return;
  3323. }
  3324. # endif
  3325. if (!output_unneeded)
  3326. BCOPY((word *)GC_dirty_pages, GC_grungy_pages, sizeof(GC_dirty_pages));
  3327. BZERO((word *)GC_dirty_pages, (sizeof GC_dirty_pages));
  3328. GC_protect_heap();
  3329. }
  3330. /*
  3331. * Acquiring the allocation lock here is dangerous, since this
  3332. * can be called from within GC_call_with_alloc_lock, and the cord
  3333. * package does so. On systems that allow nested lock acquisition, this
  3334. * happens to work.
  3335. */
  3336. /* We no longer wrap read by default, since that was causing too many */
  3337. /* problems. It is preferred that the client instead avoids writing */
  3338. /* to the write-protected heap with a system call. */
  3339. # ifdef CHECKSUMS
  3340. GC_INNER GC_bool GC_page_was_ever_dirty(struct hblk * h GC_ATTR_UNUSED)
  3341. {
  3342. # if defined(GWW_VDB)
  3343. if (GC_GWW_AVAILABLE())
  3344. return GC_gww_page_was_ever_dirty(h);
  3345. # endif
  3346. return(TRUE);
  3347. }
  3348. # endif /* CHECKSUMS */
  3349. #endif /* MPROTECT_VDB */
  3350. #ifdef PROC_VDB
  3351. /* See DEFAULT_VDB for interface descriptions. */
  3352. /* This implementation assumes a Solaris 2.X like /proc */
  3353. /* pseudo-file-system from which we can read page modified bits. This */
  3354. /* facility is far from optimal (e.g. we would like to get the info for */
  3355. /* only some of the address space), but it avoids intercepting system */
  3356. /* calls. */
  3357. # include <errno.h>
  3358. # include <sys/types.h>
  3359. # include <sys/signal.h>
  3360. # include <sys/syscall.h>
  3361. # include <sys/stat.h>
  3362. # ifdef GC_NO_SYS_FAULT_H
  3363. /* This exists only to check PROC_VDB code compilation (on Linux). */
  3364. # define PG_MODIFIED 1
  3365. struct prpageheader {
  3366. int dummy[2]; /* pr_tstamp */
  3367. unsigned long pr_nmap;
  3368. unsigned long pr_npage;
  3369. };
  3370. struct prasmap {
  3371. char *pr_vaddr;
  3372. size_t pr_npage;
  3373. char dummy1[64+8]; /* pr_mapname, pr_offset */
  3374. unsigned pr_mflags;
  3375. unsigned pr_pagesize;
  3376. int dummy2[2];
  3377. };
  3378. # else
  3379. # include <sys/fault.h>
  3380. # include <sys/procfs.h>
  3381. # endif
  3382. # define INITIAL_BUF_SZ 16384
  3383. STATIC size_t GC_proc_buf_size = INITIAL_BUF_SZ;
  3384. STATIC char *GC_proc_buf = NULL;
  3385. STATIC int GC_proc_fd = 0;
  3386. GC_INNER GC_bool GC_dirty_init(void)
  3387. {
  3388. char buf[40];
  3389. if (GC_bytes_allocd != 0 || GC_bytes_allocd_before_gc != 0) {
  3390. memset(GC_written_pages, 0xff, sizeof(page_hash_table));
  3391. GC_VERBOSE_LOG_PRINTF(
  3392. "Allocated %lu bytes: all pages may have been written\n",
  3393. (unsigned long)(GC_bytes_allocd + GC_bytes_allocd_before_gc));
  3394. }
  3395. (void)snprintf(buf, sizeof(buf), "/proc/%ld/pagedata", (long)getpid());
  3396. buf[sizeof(buf) - 1] = '\0';
  3397. GC_proc_fd = open(buf, O_RDONLY);
  3398. if (GC_proc_fd < 0) {
  3399. WARN("/proc open failed; cannot enable GC incremental mode\n", 0);
  3400. return FALSE;
  3401. }
  3402. if (syscall(SYS_fcntl, GC_proc_fd, F_SETFD, FD_CLOEXEC) == -1)
  3403. WARN("Could not set FD_CLOEXEC for /proc\n", 0);
  3404. GC_proc_buf = GC_scratch_alloc(GC_proc_buf_size);
  3405. if (GC_proc_buf == NULL)
  3406. ABORT("Insufficient space for /proc read");
  3407. return TRUE;
  3408. }
  3409. # define READ read
  3410. GC_INNER void GC_read_dirty(GC_bool output_unneeded)
  3411. {
  3412. int nmaps;
  3413. char * bufp = GC_proc_buf;
  3414. int i;
  3415. BZERO(GC_grungy_pages, sizeof(GC_grungy_pages));
  3416. if (READ(GC_proc_fd, bufp, GC_proc_buf_size) <= 0) {
  3417. /* Retry with larger buffer. */
  3418. size_t new_size = 2 * GC_proc_buf_size;
  3419. char *new_buf;
  3420. WARN("/proc read failed: GC_proc_buf_size = %" WARN_PRIdPTR "\n",
  3421. (signed_word)GC_proc_buf_size);
  3422. new_buf = GC_scratch_alloc(new_size);
  3423. if (new_buf != 0) {
  3424. GC_scratch_recycle_no_gww(bufp, GC_proc_buf_size);
  3425. GC_proc_buf = bufp = new_buf;
  3426. GC_proc_buf_size = new_size;
  3427. }
  3428. if (READ(GC_proc_fd, bufp, GC_proc_buf_size) <= 0) {
  3429. WARN("Insufficient space for /proc read\n", 0);
  3430. /* Punt: */
  3431. if (!output_unneeded)
  3432. memset(GC_grungy_pages, 0xff, sizeof (page_hash_table));
  3433. memset(GC_written_pages, 0xff, sizeof(page_hash_table));
  3434. return;
  3435. }
  3436. }
  3437. /* Copy dirty bits into GC_grungy_pages */
  3438. nmaps = ((struct prpageheader *)bufp) -> pr_nmap;
  3439. # ifdef DEBUG_DIRTY_BITS
  3440. GC_log_printf("Proc VDB read: pr_nmap= %u, pr_npage= %lu\n",
  3441. nmaps, ((struct prpageheader *)bufp)->pr_npage);
  3442. # endif
  3443. # if defined(GC_NO_SYS_FAULT_H) && defined(CPPCHECK)
  3444. GC_noop1(((struct prpageheader *)bufp)->dummy[0]);
  3445. # endif
  3446. bufp += sizeof(struct prpageheader);
  3447. for (i = 0; i < nmaps; i++) {
  3448. struct prasmap * map = (struct prasmap *)bufp;
  3449. ptr_t vaddr = (ptr_t)(map -> pr_vaddr);
  3450. unsigned long npages = map -> pr_npage;
  3451. unsigned pagesize = map -> pr_pagesize;
  3452. ptr_t limit;
  3453. # if defined(GC_NO_SYS_FAULT_H) && defined(CPPCHECK)
  3454. GC_noop1(map->dummy1[0] + map->dummy2[0]);
  3455. # endif
  3456. # ifdef DEBUG_DIRTY_BITS
  3457. GC_log_printf(
  3458. "pr_vaddr= %p, npage= %lu, mflags= 0x%x, pagesize= 0x%x\n",
  3459. (void *)vaddr, npages, map->pr_mflags, pagesize);
  3460. # endif
  3461. bufp += sizeof(struct prasmap);
  3462. limit = vaddr + pagesize * npages;
  3463. for (; (word)vaddr < (word)limit; vaddr += pagesize) {
  3464. if ((*bufp++) & PG_MODIFIED) {
  3465. struct hblk * h;
  3466. ptr_t next_vaddr = vaddr + pagesize;
  3467. # ifdef DEBUG_DIRTY_BITS
  3468. GC_log_printf("dirty page at: %p\n", (void *)vaddr);
  3469. # endif
  3470. for (h = (struct hblk *)vaddr;
  3471. (word)h < (word)next_vaddr; h++) {
  3472. word index = PHT_HASH(h);
  3473. set_pht_entry_from_index(GC_grungy_pages, index);
  3474. }
  3475. }
  3476. }
  3477. bufp = (char *)(((word)bufp + (sizeof(long)-1))
  3478. & ~(word)(sizeof(long)-1));
  3479. }
  3480. # ifdef DEBUG_DIRTY_BITS
  3481. GC_log_printf("Proc VDB read done\n");
  3482. # endif
  3483. /* Update GC_written_pages (even if output_unneeded). */
  3484. GC_or_pages(GC_written_pages, GC_grungy_pages);
  3485. }
  3486. # undef READ
  3487. #endif /* PROC_VDB */
  3488. #ifdef PCR_VDB
  3489. # include "vd/PCR_VD.h"
  3490. # define NPAGES (32*1024) /* 128 MB */
  3491. PCR_VD_DB GC_grungy_bits[NPAGES];
  3492. STATIC ptr_t GC_vd_base = NULL;
  3493. /* Address corresponding to GC_grungy_bits[0] */
  3494. /* HBLKSIZE aligned. */
  3495. GC_INNER GC_bool GC_dirty_init(void)
  3496. {
  3497. /* For the time being, we assume the heap generally grows up */
  3498. GC_vd_base = GC_heap_sects[0].hs_start;
  3499. if (GC_vd_base == 0) {
  3500. ABORT("Bad initial heap segment");
  3501. }
  3502. if (PCR_VD_Start(HBLKSIZE, GC_vd_base, NPAGES*HBLKSIZE)
  3503. != PCR_ERes_okay) {
  3504. ABORT("Dirty bit initialization failed");
  3505. }
  3506. return TRUE;
  3507. }
  3508. GC_INNER void GC_read_dirty(GC_bool output_unneeded GC_ATTR_UNUSED)
  3509. {
  3510. /* lazily enable dirty bits on newly added heap sects */
  3511. {
  3512. static int onhs = 0;
  3513. int nhs = GC_n_heap_sects;
  3514. for(; onhs < nhs; onhs++) {
  3515. PCR_VD_WriteProtectEnable(
  3516. GC_heap_sects[onhs].hs_start,
  3517. GC_heap_sects[onhs].hs_bytes );
  3518. }
  3519. }
  3520. if (PCR_VD_Clear(GC_vd_base, NPAGES*HBLKSIZE, GC_grungy_bits)
  3521. != PCR_ERes_okay) {
  3522. ABORT("Dirty bit read failed");
  3523. }
  3524. }
  3525. GC_INNER GC_bool GC_page_was_dirty(struct hblk *h)
  3526. {
  3527. if ((word)h < (word)GC_vd_base
  3528. || (word)h >= (word)(GC_vd_base + NPAGES*HBLKSIZE)) {
  3529. return(TRUE);
  3530. }
  3531. return(GC_grungy_bits[h - (struct hblk *)GC_vd_base] & PCR_VD_DB_dirtyBit);
  3532. }
  3533. GC_INNER void GC_remove_protection(struct hblk *h, word nblocks,
  3534. GC_bool is_ptrfree GC_ATTR_UNUSED)
  3535. {
  3536. PCR_VD_WriteProtectDisable(h, nblocks*HBLKSIZE);
  3537. PCR_VD_WriteProtectEnable(h, nblocks*HBLKSIZE);
  3538. }
  3539. #endif /* PCR_VDB */
  3540. #if defined(MPROTECT_VDB) && defined(DARWIN)
  3541. /* The following sources were used as a "reference" for this exception
  3542. handling code:
  3543. 1. Apple's mach/xnu documentation
  3544. 2. Timothy J. Wood's "Mach Exception Handlers 101" post to the
  3545. omnigroup's macosx-dev list.
  3546. www.omnigroup.com/mailman/archive/macosx-dev/2000-June/014178.html
  3547. 3. macosx-nat.c from Apple's GDB source code.
  3548. */
  3549. /* The bug that caused all this trouble should now be fixed. This should
  3550. eventually be removed if all goes well. */
  3551. /* #define BROKEN_EXCEPTION_HANDLING */
  3552. #include <mach/mach.h>
  3553. #include <mach/mach_error.h>
  3554. #include <mach/exception.h>
  3555. #include <mach/task.h>
  3556. #include <pthread.h>
  3557. EXTERN_C_BEGIN
  3558. /* Some of the following prototypes are missing in any header, although */
  3559. /* they are documented. Some are in mach/exc.h file. */
  3560. extern boolean_t
  3561. exc_server(mach_msg_header_t *, mach_msg_header_t *);
  3562. extern kern_return_t
  3563. exception_raise(mach_port_t, mach_port_t, mach_port_t, exception_type_t,
  3564. exception_data_t, mach_msg_type_number_t);
  3565. extern kern_return_t
  3566. exception_raise_state(mach_port_t, mach_port_t, mach_port_t, exception_type_t,
  3567. exception_data_t, mach_msg_type_number_t,
  3568. thread_state_flavor_t*, thread_state_t,
  3569. mach_msg_type_number_t, thread_state_t,
  3570. mach_msg_type_number_t*);
  3571. extern kern_return_t
  3572. exception_raise_state_identity(mach_port_t, mach_port_t, mach_port_t,
  3573. exception_type_t, exception_data_t,
  3574. mach_msg_type_number_t, thread_state_flavor_t*,
  3575. thread_state_t, mach_msg_type_number_t,
  3576. thread_state_t, mach_msg_type_number_t*);
  3577. GC_API_OSCALL kern_return_t
  3578. catch_exception_raise(mach_port_t exception_port, mach_port_t thread,
  3579. mach_port_t task, exception_type_t exception,
  3580. exception_data_t code,
  3581. mach_msg_type_number_t code_count);
  3582. GC_API_OSCALL kern_return_t
  3583. catch_exception_raise_state(mach_port_name_t exception_port,
  3584. int exception, exception_data_t code,
  3585. mach_msg_type_number_t codeCnt, int flavor,
  3586. thread_state_t old_state, int old_stateCnt,
  3587. thread_state_t new_state, int new_stateCnt);
  3588. GC_API_OSCALL kern_return_t
  3589. catch_exception_raise_state_identity(mach_port_name_t exception_port,
  3590. mach_port_t thread, mach_port_t task, int exception,
  3591. exception_data_t code, mach_msg_type_number_t codeCnt,
  3592. int flavor, thread_state_t old_state, int old_stateCnt,
  3593. thread_state_t new_state, int new_stateCnt);
  3594. EXTERN_C_END
  3595. /* These should never be called, but just in case... */
  3596. GC_API_OSCALL kern_return_t
  3597. catch_exception_raise_state(mach_port_name_t exception_port GC_ATTR_UNUSED,
  3598. int exception GC_ATTR_UNUSED, exception_data_t code GC_ATTR_UNUSED,
  3599. mach_msg_type_number_t codeCnt GC_ATTR_UNUSED, int flavor GC_ATTR_UNUSED,
  3600. thread_state_t old_state GC_ATTR_UNUSED, int old_stateCnt GC_ATTR_UNUSED,
  3601. thread_state_t new_state GC_ATTR_UNUSED, int new_stateCnt GC_ATTR_UNUSED)
  3602. {
  3603. ABORT_RET("Unexpected catch_exception_raise_state invocation");
  3604. return(KERN_INVALID_ARGUMENT);
  3605. }
  3606. GC_API_OSCALL kern_return_t
  3607. catch_exception_raise_state_identity(
  3608. mach_port_name_t exception_port GC_ATTR_UNUSED,
  3609. mach_port_t thread GC_ATTR_UNUSED, mach_port_t task GC_ATTR_UNUSED,
  3610. int exception GC_ATTR_UNUSED, exception_data_t code GC_ATTR_UNUSED,
  3611. mach_msg_type_number_t codeCnt GC_ATTR_UNUSED, int flavor GC_ATTR_UNUSED,
  3612. thread_state_t old_state GC_ATTR_UNUSED, int old_stateCnt GC_ATTR_UNUSED,
  3613. thread_state_t new_state GC_ATTR_UNUSED, int new_stateCnt GC_ATTR_UNUSED)
  3614. {
  3615. ABORT_RET("Unexpected catch_exception_raise_state_identity invocation");
  3616. return(KERN_INVALID_ARGUMENT);
  3617. }
  3618. #define MAX_EXCEPTION_PORTS 16
  3619. static struct {
  3620. mach_msg_type_number_t count;
  3621. exception_mask_t masks[MAX_EXCEPTION_PORTS];
  3622. exception_handler_t ports[MAX_EXCEPTION_PORTS];
  3623. exception_behavior_t behaviors[MAX_EXCEPTION_PORTS];
  3624. thread_state_flavor_t flavors[MAX_EXCEPTION_PORTS];
  3625. } GC_old_exc_ports;
  3626. STATIC struct ports_s {
  3627. void (*volatile os_callback[3])(void);
  3628. mach_port_t exception;
  3629. # if defined(THREADS)
  3630. mach_port_t reply;
  3631. # endif
  3632. } GC_ports = {
  3633. {
  3634. /* This is to prevent stripping these routines as dead. */
  3635. (void (*)(void))catch_exception_raise,
  3636. (void (*)(void))catch_exception_raise_state,
  3637. (void (*)(void))catch_exception_raise_state_identity
  3638. },
  3639. # ifdef THREADS
  3640. 0, /* for 'exception' */
  3641. # endif
  3642. 0
  3643. };
  3644. typedef struct {
  3645. mach_msg_header_t head;
  3646. } GC_msg_t;
  3647. typedef enum {
  3648. GC_MP_NORMAL,
  3649. GC_MP_DISCARDING,
  3650. GC_MP_STOPPED
  3651. } GC_mprotect_state_t;
  3652. #ifdef THREADS
  3653. /* FIXME: 1 and 2 seem to be safe to use in the msgh_id field, but it */
  3654. /* is not documented. Use the source and see if they should be OK. */
  3655. # define ID_STOP 1
  3656. # define ID_RESUME 2
  3657. /* This value is only used on the reply port. */
  3658. # define ID_ACK 3
  3659. STATIC GC_mprotect_state_t GC_mprotect_state = GC_MP_NORMAL;
  3660. /* The following should ONLY be called when the world is stopped. */
  3661. STATIC void GC_mprotect_thread_notify(mach_msg_id_t id)
  3662. {
  3663. struct buf_s {
  3664. GC_msg_t msg;
  3665. mach_msg_trailer_t trailer;
  3666. } buf;
  3667. mach_msg_return_t r;
  3668. /* remote, local */
  3669. buf.msg.head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
  3670. buf.msg.head.msgh_size = sizeof(buf.msg);
  3671. buf.msg.head.msgh_remote_port = GC_ports.exception;
  3672. buf.msg.head.msgh_local_port = MACH_PORT_NULL;
  3673. buf.msg.head.msgh_id = id;
  3674. r = mach_msg(&buf.msg.head, MACH_SEND_MSG | MACH_RCV_MSG | MACH_RCV_LARGE,
  3675. sizeof(buf.msg), sizeof(buf), GC_ports.reply,
  3676. MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
  3677. if (r != MACH_MSG_SUCCESS)
  3678. ABORT("mach_msg failed in GC_mprotect_thread_notify");
  3679. if (buf.msg.head.msgh_id != ID_ACK)
  3680. ABORT("Invalid ack in GC_mprotect_thread_notify");
  3681. }
  3682. /* Should only be called by the mprotect thread */
  3683. STATIC void GC_mprotect_thread_reply(void)
  3684. {
  3685. GC_msg_t msg;
  3686. mach_msg_return_t r;
  3687. /* remote, local */
  3688. msg.head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
  3689. msg.head.msgh_size = sizeof(msg);
  3690. msg.head.msgh_remote_port = GC_ports.reply;
  3691. msg.head.msgh_local_port = MACH_PORT_NULL;
  3692. msg.head.msgh_id = ID_ACK;
  3693. r = mach_msg(&msg.head, MACH_SEND_MSG, sizeof(msg), 0, MACH_PORT_NULL,
  3694. MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
  3695. if (r != MACH_MSG_SUCCESS)
  3696. ABORT("mach_msg failed in GC_mprotect_thread_reply");
  3697. }
  3698. GC_INNER void GC_mprotect_stop(void)
  3699. {
  3700. GC_mprotect_thread_notify(ID_STOP);
  3701. }
  3702. GC_INNER void GC_mprotect_resume(void)
  3703. {
  3704. GC_mprotect_thread_notify(ID_RESUME);
  3705. }
  3706. #else
  3707. /* The compiler should optimize away any GC_mprotect_state computations */
  3708. # define GC_mprotect_state GC_MP_NORMAL
  3709. #endif /* !THREADS */
  3710. STATIC void *GC_mprotect_thread(void *arg)
  3711. {
  3712. mach_msg_return_t r;
  3713. /* These two structures contain some private kernel data. We don't */
  3714. /* need to access any of it so we don't bother defining a proper */
  3715. /* struct. The correct definitions are in the xnu source code. */
  3716. struct reply_s {
  3717. mach_msg_header_t head;
  3718. char data[256];
  3719. } reply;
  3720. struct msg_s {
  3721. mach_msg_header_t head;
  3722. mach_msg_body_t msgh_body;
  3723. char data[1024];
  3724. } msg;
  3725. mach_msg_id_t id;
  3726. if ((word)arg == (word)-1) return 0; /* to make compiler happy */
  3727. # if defined(CPPCHECK)
  3728. reply.data[0] = 0; /* to prevent "field unused" warnings */
  3729. msg.data[0] = 0;
  3730. # endif
  3731. # if defined(THREADS) && !defined(GC_NO_THREADS_DISCOVERY)
  3732. GC_darwin_register_mach_handler_thread(mach_thread_self());
  3733. # endif
  3734. for(;;) {
  3735. r = mach_msg(&msg.head, MACH_RCV_MSG | MACH_RCV_LARGE |
  3736. (GC_mprotect_state == GC_MP_DISCARDING ? MACH_RCV_TIMEOUT : 0),
  3737. 0, sizeof(msg), GC_ports.exception,
  3738. GC_mprotect_state == GC_MP_DISCARDING ? 0
  3739. : MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
  3740. id = r == MACH_MSG_SUCCESS ? msg.head.msgh_id : -1;
  3741. # if defined(THREADS)
  3742. if(GC_mprotect_state == GC_MP_DISCARDING) {
  3743. if(r == MACH_RCV_TIMED_OUT) {
  3744. GC_mprotect_state = GC_MP_STOPPED;
  3745. GC_mprotect_thread_reply();
  3746. continue;
  3747. }
  3748. if(r == MACH_MSG_SUCCESS && (id == ID_STOP || id == ID_RESUME))
  3749. ABORT("Out of order mprotect thread request");
  3750. }
  3751. # endif /* THREADS */
  3752. if (r != MACH_MSG_SUCCESS) {
  3753. ABORT_ARG2("mach_msg failed",
  3754. ": errcode= %d (%s)", (int)r, mach_error_string(r));
  3755. }
  3756. switch(id) {
  3757. # if defined(THREADS)
  3758. case ID_STOP:
  3759. if(GC_mprotect_state != GC_MP_NORMAL)
  3760. ABORT("Called mprotect_stop when state wasn't normal");
  3761. GC_mprotect_state = GC_MP_DISCARDING;
  3762. break;
  3763. case ID_RESUME:
  3764. if(GC_mprotect_state != GC_MP_STOPPED)
  3765. ABORT("Called mprotect_resume when state wasn't stopped");
  3766. GC_mprotect_state = GC_MP_NORMAL;
  3767. GC_mprotect_thread_reply();
  3768. break;
  3769. # endif /* THREADS */
  3770. default:
  3771. /* Handle the message (calls catch_exception_raise) */
  3772. if(!exc_server(&msg.head, &reply.head))
  3773. ABORT("exc_server failed");
  3774. /* Send the reply */
  3775. r = mach_msg(&reply.head, MACH_SEND_MSG, reply.head.msgh_size, 0,
  3776. MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
  3777. MACH_PORT_NULL);
  3778. if(r != MACH_MSG_SUCCESS) {
  3779. /* This will fail if the thread dies, but the thread */
  3780. /* shouldn't die... */
  3781. # ifdef BROKEN_EXCEPTION_HANDLING
  3782. GC_err_printf("mach_msg failed with %d %s while sending "
  3783. "exc reply\n", (int)r, mach_error_string(r));
  3784. # else
  3785. ABORT("mach_msg failed while sending exception reply");
  3786. # endif
  3787. }
  3788. } /* switch */
  3789. } /* for(;;) */
  3790. }
  3791. /* All this SIGBUS code shouldn't be necessary. All protection faults should
  3792. be going through the mach exception handler. However, it seems a SIGBUS is
  3793. occasionally sent for some unknown reason. Even more odd, it seems to be
  3794. meaningless and safe to ignore. */
  3795. #ifdef BROKEN_EXCEPTION_HANDLING
  3796. /* Updates to this aren't atomic, but the SIGBUS'es seem pretty rare. */
  3797. /* Even if this doesn't get updated property, it isn't really a problem. */
  3798. STATIC int GC_sigbus_count = 0;
  3799. STATIC void GC_darwin_sigbus(int num, siginfo_t *sip, void *context)
  3800. {
  3801. if (num != SIGBUS)
  3802. ABORT("Got a non-sigbus signal in the sigbus handler");
  3803. /* Ugh... some seem safe to ignore, but too many in a row probably means
  3804. trouble. GC_sigbus_count is reset for each mach exception that is
  3805. handled */
  3806. if (GC_sigbus_count >= 8) {
  3807. ABORT("Got more than 8 SIGBUSs in a row!");
  3808. } else {
  3809. GC_sigbus_count++;
  3810. WARN("Ignoring SIGBUS\n", 0);
  3811. }
  3812. }
  3813. #endif /* BROKEN_EXCEPTION_HANDLING */
  3814. GC_INNER GC_bool GC_mprotect_dirty_init(void)
  3815. {
  3816. kern_return_t r;
  3817. mach_port_t me;
  3818. pthread_t thread;
  3819. pthread_attr_t attr;
  3820. exception_mask_t mask;
  3821. # ifdef CAN_HANDLE_FORK
  3822. if (GC_handle_fork) {
  3823. /* To both support GC incremental mode and GC functions usage in */
  3824. /* the forked child, pthread_atfork should be used to install */
  3825. /* handlers that switch off GC_incremental in the child */
  3826. /* gracefully (unprotecting all pages and clearing */
  3827. /* GC_mach_handler_thread). For now, we just disable incremental */
  3828. /* mode if fork() handling is requested by the client. */
  3829. WARN("Can't turn on GC incremental mode as fork()"
  3830. " handling requested\n", 0);
  3831. return FALSE;
  3832. }
  3833. # endif
  3834. GC_VERBOSE_LOG_PRINTF("Initializing mach/darwin mprotect"
  3835. " virtual dirty bit implementation\n");
  3836. # ifdef BROKEN_EXCEPTION_HANDLING
  3837. WARN("Enabling workarounds for various darwin "
  3838. "exception handling bugs\n", 0);
  3839. # endif
  3840. if (GC_page_size % HBLKSIZE != 0) {
  3841. ABORT("Page size not multiple of HBLKSIZE");
  3842. }
  3843. GC_task_self = me = mach_task_self();
  3844. r = mach_port_allocate(me, MACH_PORT_RIGHT_RECEIVE, &GC_ports.exception);
  3845. /* TODO: WARN and return FALSE in case of a failure. */
  3846. if (r != KERN_SUCCESS)
  3847. ABORT("mach_port_allocate failed (exception port)");
  3848. r = mach_port_insert_right(me, GC_ports.exception, GC_ports.exception,
  3849. MACH_MSG_TYPE_MAKE_SEND);
  3850. if (r != KERN_SUCCESS)
  3851. ABORT("mach_port_insert_right failed (exception port)");
  3852. # if defined(THREADS)
  3853. r = mach_port_allocate(me, MACH_PORT_RIGHT_RECEIVE, &GC_ports.reply);
  3854. if(r != KERN_SUCCESS)
  3855. ABORT("mach_port_allocate failed (reply port)");
  3856. # endif
  3857. /* The exceptions we want to catch */
  3858. mask = EXC_MASK_BAD_ACCESS;
  3859. r = task_get_exception_ports(me, mask, GC_old_exc_ports.masks,
  3860. &GC_old_exc_ports.count, GC_old_exc_ports.ports,
  3861. GC_old_exc_ports.behaviors,
  3862. GC_old_exc_ports.flavors);
  3863. if (r != KERN_SUCCESS)
  3864. ABORT("task_get_exception_ports failed");
  3865. r = task_set_exception_ports(me, mask, GC_ports.exception, EXCEPTION_DEFAULT,
  3866. GC_MACH_THREAD_STATE);
  3867. if (r != KERN_SUCCESS)
  3868. ABORT("task_set_exception_ports failed");
  3869. if (pthread_attr_init(&attr) != 0)
  3870. ABORT("pthread_attr_init failed");
  3871. if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
  3872. ABORT("pthread_attr_setdetachedstate failed");
  3873. # undef pthread_create
  3874. /* This will call the real pthread function, not our wrapper */
  3875. if (pthread_create(&thread, &attr, GC_mprotect_thread, NULL) != 0)
  3876. ABORT("pthread_create failed");
  3877. (void)pthread_attr_destroy(&attr);
  3878. /* Setup the sigbus handler for ignoring the meaningless SIGBUSs */
  3879. # ifdef BROKEN_EXCEPTION_HANDLING
  3880. {
  3881. struct sigaction sa, oldsa;
  3882. sa.sa_handler = (SIG_HNDLR_PTR)GC_darwin_sigbus;
  3883. sigemptyset(&sa.sa_mask);
  3884. sa.sa_flags = SA_RESTART|SA_SIGINFO;
  3885. /* sa.sa_restorer is deprecated and should not be initialized. */
  3886. if (sigaction(SIGBUS, &sa, &oldsa) < 0)
  3887. ABORT("sigaction failed");
  3888. if ((SIG_HNDLR_PTR)oldsa.sa_handler != SIG_DFL) {
  3889. GC_VERBOSE_LOG_PRINTF("Replaced other SIGBUS handler\n");
  3890. }
  3891. }
  3892. # endif /* BROKEN_EXCEPTION_HANDLING */
  3893. return TRUE;
  3894. }
  3895. /* The source code for Apple's GDB was used as a reference for the */
  3896. /* exception forwarding code. This code is similar to be GDB code only */
  3897. /* because there is only one way to do it. */
  3898. STATIC kern_return_t GC_forward_exception(mach_port_t thread, mach_port_t task,
  3899. exception_type_t exception,
  3900. exception_data_t data,
  3901. mach_msg_type_number_t data_count)
  3902. {
  3903. unsigned int i;
  3904. kern_return_t r;
  3905. mach_port_t port;
  3906. exception_behavior_t behavior;
  3907. thread_state_flavor_t flavor;
  3908. thread_state_data_t thread_state;
  3909. mach_msg_type_number_t thread_state_count = THREAD_STATE_MAX;
  3910. for (i=0; i < GC_old_exc_ports.count; i++)
  3911. if (GC_old_exc_ports.masks[i] & (1 << exception))
  3912. break;
  3913. if (i == GC_old_exc_ports.count)
  3914. ABORT("No handler for exception!");
  3915. port = GC_old_exc_ports.ports[i];
  3916. behavior = GC_old_exc_ports.behaviors[i];
  3917. flavor = GC_old_exc_ports.flavors[i];
  3918. if (behavior == EXCEPTION_STATE || behavior == EXCEPTION_STATE_IDENTITY) {
  3919. r = thread_get_state(thread, flavor, thread_state, &thread_state_count);
  3920. if(r != KERN_SUCCESS)
  3921. ABORT("thread_get_state failed in forward_exception");
  3922. }
  3923. switch(behavior) {
  3924. case EXCEPTION_STATE:
  3925. r = exception_raise_state(port, thread, task, exception, data, data_count,
  3926. &flavor, thread_state, thread_state_count,
  3927. thread_state, &thread_state_count);
  3928. break;
  3929. case EXCEPTION_STATE_IDENTITY:
  3930. r = exception_raise_state_identity(port, thread, task, exception, data,
  3931. data_count, &flavor, thread_state,
  3932. thread_state_count, thread_state,
  3933. &thread_state_count);
  3934. break;
  3935. /* case EXCEPTION_DEFAULT: */ /* default signal handlers */
  3936. default: /* user-supplied signal handlers */
  3937. r = exception_raise(port, thread, task, exception, data, data_count);
  3938. }
  3939. if (behavior == EXCEPTION_STATE || behavior == EXCEPTION_STATE_IDENTITY) {
  3940. r = thread_set_state(thread, flavor, thread_state, thread_state_count);
  3941. if (r != KERN_SUCCESS)
  3942. ABORT("thread_set_state failed in forward_exception");
  3943. }
  3944. return r;
  3945. }
  3946. #define FWD() GC_forward_exception(thread, task, exception, code, code_count)
  3947. #ifdef ARM32
  3948. # define DARWIN_EXC_STATE ARM_EXCEPTION_STATE
  3949. # define DARWIN_EXC_STATE_COUNT ARM_EXCEPTION_STATE_COUNT
  3950. # define DARWIN_EXC_STATE_T arm_exception_state_t
  3951. # define DARWIN_EXC_STATE_DAR THREAD_FLD_NAME(far)
  3952. #elif defined(AARCH64)
  3953. # define DARWIN_EXC_STATE ARM_EXCEPTION_STATE64
  3954. # define DARWIN_EXC_STATE_COUNT ARM_EXCEPTION_STATE64_COUNT
  3955. # define DARWIN_EXC_STATE_T arm_exception_state64_t
  3956. # define DARWIN_EXC_STATE_DAR THREAD_FLD_NAME(far)
  3957. #elif defined(POWERPC)
  3958. # if CPP_WORDSZ == 32
  3959. # define DARWIN_EXC_STATE PPC_EXCEPTION_STATE
  3960. # define DARWIN_EXC_STATE_COUNT PPC_EXCEPTION_STATE_COUNT
  3961. # define DARWIN_EXC_STATE_T ppc_exception_state_t
  3962. # else
  3963. # define DARWIN_EXC_STATE PPC_EXCEPTION_STATE64
  3964. # define DARWIN_EXC_STATE_COUNT PPC_EXCEPTION_STATE64_COUNT
  3965. # define DARWIN_EXC_STATE_T ppc_exception_state64_t
  3966. # endif
  3967. # define DARWIN_EXC_STATE_DAR THREAD_FLD_NAME(dar)
  3968. #elif defined(I386) || defined(X86_64)
  3969. # if CPP_WORDSZ == 32
  3970. # if defined(i386_EXCEPTION_STATE_COUNT) \
  3971. && !defined(x86_EXCEPTION_STATE32_COUNT)
  3972. /* Use old naming convention for 32-bit x86. */
  3973. # define DARWIN_EXC_STATE i386_EXCEPTION_STATE
  3974. # define DARWIN_EXC_STATE_COUNT i386_EXCEPTION_STATE_COUNT
  3975. # define DARWIN_EXC_STATE_T i386_exception_state_t
  3976. # else
  3977. # define DARWIN_EXC_STATE x86_EXCEPTION_STATE32
  3978. # define DARWIN_EXC_STATE_COUNT x86_EXCEPTION_STATE32_COUNT
  3979. # define DARWIN_EXC_STATE_T x86_exception_state32_t
  3980. # endif
  3981. # else
  3982. # define DARWIN_EXC_STATE x86_EXCEPTION_STATE64
  3983. # define DARWIN_EXC_STATE_COUNT x86_EXCEPTION_STATE64_COUNT
  3984. # define DARWIN_EXC_STATE_T x86_exception_state64_t
  3985. # endif
  3986. # define DARWIN_EXC_STATE_DAR THREAD_FLD_NAME(faultvaddr)
  3987. #elif !defined(CPPCHECK)
  3988. # error FIXME for non-arm/ppc/x86 darwin
  3989. #endif
  3990. /* This violates the namespace rules but there isn't anything that can */
  3991. /* be done about it. The exception handling stuff is hard coded to */
  3992. /* call this. catch_exception_raise, catch_exception_raise_state and */
  3993. /* and catch_exception_raise_state_identity are called from OS. */
  3994. GC_API_OSCALL kern_return_t
  3995. catch_exception_raise(mach_port_t exception_port GC_ATTR_UNUSED,
  3996. mach_port_t thread, mach_port_t task GC_ATTR_UNUSED,
  3997. exception_type_t exception, exception_data_t code,
  3998. mach_msg_type_number_t code_count GC_ATTR_UNUSED)
  3999. {
  4000. kern_return_t r;
  4001. char *addr;
  4002. thread_state_flavor_t flavor = DARWIN_EXC_STATE;
  4003. mach_msg_type_number_t exc_state_count = DARWIN_EXC_STATE_COUNT;
  4004. DARWIN_EXC_STATE_T exc_state;
  4005. if (exception != EXC_BAD_ACCESS || code[0] != KERN_PROTECTION_FAILURE) {
  4006. # ifdef DEBUG_EXCEPTION_HANDLING
  4007. /* We aren't interested, pass it on to the old handler */
  4008. GC_log_printf("Exception: 0x%x Code: 0x%x 0x%x in catch...\n",
  4009. exception, code_count > 0 ? code[0] : -1,
  4010. code_count > 1 ? code[1] : -1);
  4011. # endif
  4012. return FWD();
  4013. }
  4014. r = thread_get_state(thread, flavor, (natural_t*)&exc_state,
  4015. &exc_state_count);
  4016. if(r != KERN_SUCCESS) {
  4017. /* The thread is supposed to be suspended while the exception */
  4018. /* handler is called. This shouldn't fail. */
  4019. # ifdef BROKEN_EXCEPTION_HANDLING
  4020. GC_err_printf("thread_get_state failed in catch_exception_raise\n");
  4021. return KERN_SUCCESS;
  4022. # else
  4023. ABORT("thread_get_state failed in catch_exception_raise");
  4024. # endif
  4025. }
  4026. /* This is the address that caused the fault */
  4027. addr = (char*) exc_state.DARWIN_EXC_STATE_DAR;
  4028. if (!is_header_found_async(addr)) {
  4029. /* Ugh... just like the SIGBUS problem above, it seems we get */
  4030. /* a bogus KERN_PROTECTION_FAILURE every once and a while. We wait */
  4031. /* till we get a bunch in a row before doing anything about it. */
  4032. /* If a "real" fault ever occurs it'll just keep faulting over and */
  4033. /* over and we'll hit the limit pretty quickly. */
  4034. # ifdef BROKEN_EXCEPTION_HANDLING
  4035. static char *last_fault;
  4036. static int last_fault_count;
  4037. if(addr != last_fault) {
  4038. last_fault = addr;
  4039. last_fault_count = 0;
  4040. }
  4041. if(++last_fault_count < 32) {
  4042. if(last_fault_count == 1)
  4043. WARN("Ignoring KERN_PROTECTION_FAILURE at %p\n", addr);
  4044. return KERN_SUCCESS;
  4045. }
  4046. GC_err_printf("Unexpected KERN_PROTECTION_FAILURE at %p; aborting...\n",
  4047. (void *)addr);
  4048. /* Can't pass it along to the signal handler because that is */
  4049. /* ignoring SIGBUS signals. We also shouldn't call ABORT here as */
  4050. /* signals don't always work too well from the exception handler. */
  4051. EXIT();
  4052. # else /* BROKEN_EXCEPTION_HANDLING */
  4053. /* Pass it along to the next exception handler
  4054. (which should call SIGBUS/SIGSEGV) */
  4055. return FWD();
  4056. # endif /* !BROKEN_EXCEPTION_HANDLING */
  4057. }
  4058. # ifdef BROKEN_EXCEPTION_HANDLING
  4059. /* Reset the number of consecutive SIGBUSs */
  4060. GC_sigbus_count = 0;
  4061. # endif
  4062. if (GC_mprotect_state == GC_MP_NORMAL) { /* common case */
  4063. struct hblk * h = (struct hblk*)((word)addr & ~(GC_page_size-1));
  4064. size_t i;
  4065. UNPROTECT(h, GC_page_size);
  4066. for (i = 0; i < divHBLKSZ(GC_page_size); i++) {
  4067. word index = PHT_HASH(h+i);
  4068. async_set_pht_entry_from_index(GC_dirty_pages, index);
  4069. }
  4070. } else if (GC_mprotect_state == GC_MP_DISCARDING) {
  4071. /* Lie to the thread for now. No sense UNPROTECT()ing the memory
  4072. when we're just going to PROTECT() it again later. The thread
  4073. will just fault again once it resumes */
  4074. } else {
  4075. /* Shouldn't happen, i don't think */
  4076. GC_err_printf("KERN_PROTECTION_FAILURE while world is stopped\n");
  4077. return FWD();
  4078. }
  4079. return KERN_SUCCESS;
  4080. }
  4081. #undef FWD
  4082. #ifndef NO_DESC_CATCH_EXCEPTION_RAISE
  4083. /* These symbols should have REFERENCED_DYNAMICALLY (0x10) bit set to */
  4084. /* let strip know they are not to be stripped. */
  4085. __asm__(".desc _catch_exception_raise, 0x10");
  4086. __asm__(".desc _catch_exception_raise_state, 0x10");
  4087. __asm__(".desc _catch_exception_raise_state_identity, 0x10");
  4088. #endif
  4089. #endif /* DARWIN && MPROTECT_VDB */
  4090. #ifndef HAVE_INCREMENTAL_PROTECTION_NEEDS
  4091. GC_API int GC_CALL GC_incremental_protection_needs(void)
  4092. {
  4093. return GC_PROTECTS_NONE;
  4094. }
  4095. #endif /* !HAVE_INCREMENTAL_PROTECTION_NEEDS */
  4096. #ifdef ECOS
  4097. /* Undo sbrk() redirection. */
  4098. # undef sbrk
  4099. #endif
  4100. /* If value is non-zero then allocate executable memory. */
  4101. GC_API void GC_CALL GC_set_pages_executable(int value)
  4102. {
  4103. GC_ASSERT(!GC_is_initialized);
  4104. /* Even if IGNORE_PAGES_EXECUTABLE is defined, GC_pages_executable is */
  4105. /* touched here to prevent a compiler warning. */
  4106. GC_pages_executable = (GC_bool)(value != 0);
  4107. }
  4108. /* Returns non-zero if the GC-allocated memory is executable. */
  4109. /* GC_get_pages_executable is defined after all the places */
  4110. /* where GC_get_pages_executable is undefined. */
  4111. GC_API int GC_CALL GC_get_pages_executable(void)
  4112. {
  4113. # ifdef IGNORE_PAGES_EXECUTABLE
  4114. return 1; /* Always allocate executable memory. */
  4115. # else
  4116. return (int)GC_pages_executable;
  4117. # endif
  4118. }
  4119. /* Call stack save code for debugging. Should probably be in */
  4120. /* mach_dep.c, but that requires reorganization. */
  4121. /* I suspect the following works for most X86 *nix variants, so */
  4122. /* long as the frame pointer is explicitly stored. In the case of gcc, */
  4123. /* compiler flags (e.g. -fomit-frame-pointer) determine whether it is. */
  4124. #if defined(I386) && defined(LINUX) && defined(SAVE_CALL_CHAIN)
  4125. # include <features.h>
  4126. struct frame {
  4127. struct frame *fr_savfp;
  4128. long fr_savpc;
  4129. # if NARGS > 0
  4130. long fr_arg[NARGS]; /* All the arguments go here. */
  4131. # endif
  4132. };
  4133. #endif
  4134. #if defined(SPARC)
  4135. # if defined(LINUX)
  4136. # include <features.h>
  4137. struct frame {
  4138. long fr_local[8];
  4139. long fr_arg[6];
  4140. struct frame *fr_savfp;
  4141. long fr_savpc;
  4142. # ifndef __arch64__
  4143. char *fr_stret;
  4144. # endif
  4145. long fr_argd[6];
  4146. long fr_argx[0];
  4147. };
  4148. # elif defined (DRSNX)
  4149. # include <sys/sparc/frame.h>
  4150. # elif defined(OPENBSD)
  4151. # include <frame.h>
  4152. # elif defined(FREEBSD) || defined(NETBSD)
  4153. # include <machine/frame.h>
  4154. # else
  4155. # include <sys/frame.h>
  4156. # endif
  4157. # if NARGS > 6
  4158. # error We only know how to get the first 6 arguments
  4159. # endif
  4160. #endif /* SPARC */
  4161. #ifdef NEED_CALLINFO
  4162. /* Fill in the pc and argument information for up to NFRAMES of my */
  4163. /* callers. Ignore my frame and my callers frame. */
  4164. #ifdef LINUX
  4165. # include <unistd.h>
  4166. #endif
  4167. #endif /* NEED_CALLINFO */
  4168. #if defined(GC_HAVE_BUILTIN_BACKTRACE)
  4169. # ifdef _MSC_VER
  4170. # include "private/msvc_dbg.h"
  4171. # else
  4172. # include <execinfo.h>
  4173. # endif
  4174. #endif
  4175. #ifdef SAVE_CALL_CHAIN
  4176. #if NARGS == 0 && NFRAMES % 2 == 0 /* No padding */ \
  4177. && defined(GC_HAVE_BUILTIN_BACKTRACE)
  4178. #ifdef REDIRECT_MALLOC
  4179. /* Deal with possible malloc calls in backtrace by omitting */
  4180. /* the infinitely recursing backtrace. */
  4181. # ifdef THREADS
  4182. __thread /* If your compiler doesn't understand this */
  4183. /* you could use something like pthread_getspecific. */
  4184. # endif
  4185. GC_bool GC_in_save_callers = FALSE;
  4186. #endif
  4187. GC_INNER void GC_save_callers(struct callinfo info[NFRAMES])
  4188. {
  4189. void * tmp_info[NFRAMES + 1];
  4190. int npcs, i;
  4191. # define IGNORE_FRAMES 1
  4192. /* We retrieve NFRAMES+1 pc values, but discard the first, since it */
  4193. /* points to our own frame. */
  4194. # ifdef REDIRECT_MALLOC
  4195. if (GC_in_save_callers) {
  4196. info[0].ci_pc = (word)(&GC_save_callers);
  4197. for (i = 1; i < NFRAMES; ++i) info[i].ci_pc = 0;
  4198. return;
  4199. }
  4200. GC_in_save_callers = TRUE;
  4201. # endif
  4202. GC_ASSERT(I_HOLD_LOCK());
  4203. /* backtrace may call dl_iterate_phdr which is also */
  4204. /* used by GC_register_dynamic_libraries, and */
  4205. /* dl_iterate_phdr is not guaranteed to be reentrant. */
  4206. GC_STATIC_ASSERT(sizeof(struct callinfo) == sizeof(void *));
  4207. npcs = backtrace((void **)tmp_info, NFRAMES + IGNORE_FRAMES);
  4208. if (npcs > IGNORE_FRAMES)
  4209. BCOPY(&tmp_info[IGNORE_FRAMES], info,
  4210. (npcs - IGNORE_FRAMES) * sizeof(void *));
  4211. for (i = npcs - IGNORE_FRAMES; i < NFRAMES; ++i) info[i].ci_pc = 0;
  4212. # ifdef REDIRECT_MALLOC
  4213. GC_in_save_callers = FALSE;
  4214. # endif
  4215. }
  4216. #else /* No builtin backtrace; do it ourselves */
  4217. #if (defined(OPENBSD) || defined(NETBSD) || defined(FREEBSD)) && defined(SPARC)
  4218. # define FR_SAVFP fr_fp
  4219. # define FR_SAVPC fr_pc
  4220. #else
  4221. # define FR_SAVFP fr_savfp
  4222. # define FR_SAVPC fr_savpc
  4223. #endif
  4224. #if defined(SPARC) && (defined(__arch64__) || defined(__sparcv9))
  4225. # define BIAS 2047
  4226. #else
  4227. # define BIAS 0
  4228. #endif
  4229. GC_INNER void GC_save_callers(struct callinfo info[NFRAMES])
  4230. {
  4231. struct frame *frame;
  4232. struct frame *fp;
  4233. int nframes = 0;
  4234. # ifdef I386
  4235. /* We assume this is turned on only with gcc as the compiler. */
  4236. asm("movl %%ebp,%0" : "=r"(frame));
  4237. fp = frame;
  4238. # else
  4239. frame = (struct frame *)GC_save_regs_in_stack();
  4240. fp = (struct frame *)((long) frame -> FR_SAVFP + BIAS);
  4241. #endif
  4242. for (; !((word)fp HOTTER_THAN (word)frame)
  4243. && !((word)GC_stackbottom HOTTER_THAN (word)fp)
  4244. && nframes < NFRAMES;
  4245. fp = (struct frame *)((long) fp -> FR_SAVFP + BIAS), nframes++) {
  4246. # if NARGS > 0
  4247. int i;
  4248. # endif
  4249. info[nframes].ci_pc = fp->FR_SAVPC;
  4250. # if NARGS > 0
  4251. for (i = 0; i < NARGS; i++) {
  4252. info[nframes].ci_arg[i] = ~(fp->fr_arg[i]);
  4253. }
  4254. # endif /* NARGS > 0 */
  4255. }
  4256. if (nframes < NFRAMES) info[nframes].ci_pc = 0;
  4257. }
  4258. #endif /* No builtin backtrace */
  4259. #endif /* SAVE_CALL_CHAIN */
  4260. #ifdef NEED_CALLINFO
  4261. /* Print info to stderr. We do NOT hold the allocation lock */
  4262. GC_INNER void GC_print_callers(struct callinfo info[NFRAMES])
  4263. {
  4264. int i;
  4265. static int reentry_count = 0;
  4266. GC_bool stop = FALSE;
  4267. DCL_LOCK_STATE;
  4268. /* FIXME: This should probably use a different lock, so that we */
  4269. /* become callable with or without the allocation lock. */
  4270. LOCK();
  4271. ++reentry_count;
  4272. UNLOCK();
  4273. # if NFRAMES == 1
  4274. GC_err_printf("\tCaller at allocation:\n");
  4275. # else
  4276. GC_err_printf("\tCall chain at allocation:\n");
  4277. # endif
  4278. for (i = 0; i < NFRAMES && !stop; i++) {
  4279. if (info[i].ci_pc == 0) break;
  4280. # if NARGS > 0
  4281. {
  4282. int j;
  4283. GC_err_printf("\t\targs: ");
  4284. for (j = 0; j < NARGS; j++) {
  4285. if (j != 0) GC_err_printf(", ");
  4286. GC_err_printf("%d (0x%X)", ~(info[i].ci_arg[j]),
  4287. ~(info[i].ci_arg[j]));
  4288. }
  4289. GC_err_printf("\n");
  4290. }
  4291. # endif
  4292. if (reentry_count > 1) {
  4293. /* We were called during an allocation during */
  4294. /* a previous GC_print_callers call; punt. */
  4295. GC_err_printf("\t\t##PC##= 0x%lx\n",
  4296. (unsigned long)info[i].ci_pc);
  4297. continue;
  4298. }
  4299. {
  4300. char buf[40];
  4301. char *name;
  4302. # if defined(GC_HAVE_BUILTIN_BACKTRACE) \
  4303. && !defined(GC_BACKTRACE_SYMBOLS_BROKEN)
  4304. char **sym_name =
  4305. backtrace_symbols((void **)(&(info[i].ci_pc)), 1);
  4306. if (sym_name != NULL) {
  4307. name = sym_name[0];
  4308. } else
  4309. # endif
  4310. /* else */ {
  4311. (void)snprintf(buf, sizeof(buf), "##PC##= 0x%lx",
  4312. (unsigned long)info[i].ci_pc);
  4313. buf[sizeof(buf) - 1] = '\0';
  4314. name = buf;
  4315. }
  4316. # if defined(LINUX) && !defined(SMALL_CONFIG)
  4317. /* Try for a line number. */
  4318. {
  4319. FILE *pipe;
  4320. # define EXE_SZ 100
  4321. static char exe_name[EXE_SZ];
  4322. # define CMD_SZ 200
  4323. char cmd_buf[CMD_SZ];
  4324. # define RESULT_SZ 200
  4325. static char result_buf[RESULT_SZ];
  4326. size_t result_len;
  4327. char *old_preload;
  4328. # define PRELOAD_SZ 200
  4329. char preload_buf[PRELOAD_SZ];
  4330. static GC_bool found_exe_name = FALSE;
  4331. static GC_bool will_fail = FALSE;
  4332. int ret_code;
  4333. /* Try to get it via a hairy and expensive scheme. */
  4334. /* First we get the name of the executable: */
  4335. if (will_fail) goto out;
  4336. if (!found_exe_name) {
  4337. ret_code = readlink("/proc/self/exe", exe_name, EXE_SZ);
  4338. if (ret_code < 0 || ret_code >= EXE_SZ
  4339. || exe_name[0] != '/') {
  4340. will_fail = TRUE; /* Don't try again. */
  4341. goto out;
  4342. }
  4343. exe_name[ret_code] = '\0';
  4344. found_exe_name = TRUE;
  4345. }
  4346. /* Then we use popen to start addr2line -e <exe> <addr> */
  4347. /* There are faster ways to do this, but hopefully this */
  4348. /* isn't time critical. */
  4349. (void)snprintf(cmd_buf, sizeof(cmd_buf),
  4350. "/usr/bin/addr2line -f -e %s 0x%lx",
  4351. exe_name, (unsigned long)info[i].ci_pc);
  4352. cmd_buf[sizeof(cmd_buf) - 1] = '\0';
  4353. old_preload = GETENV("LD_PRELOAD");
  4354. if (0 != old_preload) {
  4355. size_t old_len = strlen(old_preload);
  4356. if (old_len >= PRELOAD_SZ) {
  4357. will_fail = TRUE;
  4358. goto out;
  4359. }
  4360. BCOPY(old_preload, preload_buf, old_len + 1);
  4361. unsetenv ("LD_PRELOAD");
  4362. }
  4363. pipe = popen(cmd_buf, "r");
  4364. if (0 != old_preload
  4365. && 0 != setenv ("LD_PRELOAD", preload_buf, 0)) {
  4366. WARN("Failed to reset LD_PRELOAD\n", 0);
  4367. }
  4368. if (pipe == NULL
  4369. || (result_len = fread(result_buf, 1,
  4370. RESULT_SZ - 1, pipe)) == 0) {
  4371. if (pipe != NULL) pclose(pipe);
  4372. will_fail = TRUE;
  4373. goto out;
  4374. }
  4375. if (result_buf[result_len - 1] == '\n') --result_len;
  4376. result_buf[result_len] = 0;
  4377. if (result_buf[0] == '?'
  4378. || (result_buf[result_len-2] == ':'
  4379. && result_buf[result_len-1] == '0')) {
  4380. pclose(pipe);
  4381. goto out;
  4382. }
  4383. /* Get rid of embedded newline, if any. Test for "main" */
  4384. {
  4385. char * nl = strchr(result_buf, '\n');
  4386. if (nl != NULL
  4387. && (word)nl < (word)(result_buf + result_len)) {
  4388. *nl = ':';
  4389. }
  4390. if (strncmp(result_buf, "main", nl - result_buf) == 0) {
  4391. stop = TRUE;
  4392. }
  4393. }
  4394. if (result_len < RESULT_SZ - 25) {
  4395. /* Add in hex address */
  4396. (void)snprintf(&result_buf[result_len],
  4397. sizeof(result_buf) - result_len,
  4398. " [0x%lx]", (unsigned long)info[i].ci_pc);
  4399. result_buf[sizeof(result_buf) - 1] = '\0';
  4400. }
  4401. name = result_buf;
  4402. pclose(pipe);
  4403. out:;
  4404. }
  4405. # endif /* LINUX */
  4406. GC_err_printf("\t\t%s\n", name);
  4407. # if defined(GC_HAVE_BUILTIN_BACKTRACE) \
  4408. && !defined(GC_BACKTRACE_SYMBOLS_BROKEN)
  4409. if (sym_name != NULL)
  4410. free(sym_name); /* May call GC_[debug_]free; that's OK */
  4411. # endif
  4412. }
  4413. }
  4414. LOCK();
  4415. --reentry_count;
  4416. UNLOCK();
  4417. }
  4418. #endif /* NEED_CALLINFO */
  4419. #if defined(LINUX) && defined(__ELF__) && !defined(SMALL_CONFIG)
  4420. /* Dump /proc/self/maps to GC_stderr, to enable looking up names for */
  4421. /* addresses in FIND_LEAK output. */
  4422. void GC_print_address_map(void)
  4423. {
  4424. char *maps;
  4425. GC_err_printf("---------- Begin address map ----------\n");
  4426. maps = GC_get_maps();
  4427. GC_err_puts(maps != NULL ? maps : "Failed to get map!\n");
  4428. GC_err_printf("---------- End address map ----------\n");
  4429. }
  4430. #endif /* LINUX && ELF */