JFIF       %%-))-969KKd       %%-))-969KKd! f%eK_.T  v_/n6q>e}&Cx@t7OuqySN%y%tz@ Un(quo{tS]\~LzǚPk;fϛϹ2y-=_z.NWW7DW@'4`3w3rr;hP8B%ַBe]`7Ҽo1e)弆O|4Wk*}7Su[9=U 9 |_+:@}@˵u@ g<4N<@=/ I(~}qq=y- u|. y'`3S+4$e= k4P]M^_Nou*R-,X0EI}m&LtVȱa|R\@ ʟ+YeIlY`XV^HV/c-eb du ̈́_2+DpV ` ^^->t7JydE]I 8:7#j̀iiVbp~o݃[}zwGF@-(RTJY@ Ty}X 1!2AQaq"3BR`r@PSb #4CTs0DU$EFcd?Lc4\K#E1$@CV8OƂZ5g;.141;%]6e laǃpv8)80D1ŌxLgWYc+z%:( w^PtdԣV Z:qDsh W) ͷ+~FO]"բ?eN 4)WREZ;T+}]:FRtI ѱއ>'s_[\qNhK ' ^qJv9 ]ʜ1FMzwF8ѯBIp-g`?si;|Hr%>jOh29-+-gQmBH?3P9e')>[k^OaxtLiS30ҿ6*o--I$ 1 z2+OЪ+i˺,_n3(~}StUMc \xSmGD0jMB06%') #1c6s/iaIɉgC%Yoi**MHЛ=rh ĭ總 E>Jў2+ct/^$[_kAOʕicR4qm#Lw!Squ/:e%~zMBfa|e7PUC|"/)CD\cy gڰF9(?\jU+>Cwl#>x^'a7C}LYX<@X`W8P hۂx͍q֜?de1qe* NDuTm-ߣ y+pUy*9aĺ:P4n$2&BTϵ@ a>v3uc,(uF0jˊ́a~32f2=ήZe[r!F !Bu)b FŌt%41N/֑41n1|> 1^;1=IĖEpq%"{/~M.QWDdUA6~z>kPh2Oi?Uc[`+l;՚':۾ږtoZjQ7\:Z3}~ &ڮRQH{mDq0TaM5i:5sC0x<]=Mp c!C<6]~vpxeH[AmY'iԖ_~ a(Ȕ@+a< w] wbk1#aD 9. ?p$ Qؒi-8S㨸f45t:ʙѾ.{mMshU1k\z^*#It@ v:%#iSZ.{.Vemm,Z3*;HtU8E.v'e ޴ 4WwLDe)jY*R'?wM֣ b+IfO('Y J$o޼ l.蕁~ Y Em>Y^m"r^4w}2PI7R1gV\wtVT׿w'*N{ZGN8qzrM/LO~ O~|ڞ櫮o{\dV斀AJmn E#HQg$!{XM'{u* 4O)>F.";l2z3IJ2?Fh7)rjrv@ AJlУ 0`StpGD&nƒpxΡ}P늿D@cEH҆2[9a}U/biEzu)xYR>߹q (yA~ُp \U\L\6~" U'>GJOP,ko:JGI*٢C8f8굟m#GV̐Cj]}N_]aJulE.+I&y5 6*TGHZRů}efjv"\3/3_hq՝g !ir,ܐv%~*lXccyo) 拏Qp_tT3!,Dur!CH7;9GQQmE:ÑCaƅ;zeij;d+% z#e%gdI9E5BB&۟S"=C(>{֠ ɫNUळiu>;P}حW]ouBmJS0ktRtDm+$ԫU_dq)$ ʃnLGSፑf'vlzP/_]QԂ]ȗ|W\;wTSf!m,ri{w了enP(`*.1i2.}e@;HA&_N᷸1|:Gjڒj~i/֬]1(N +^ bQq:›m*o5Y(.JPV[3ޭj֭j+i(uָ]kV)A/%X Fa?8'o>ꝣKks\_k)S%zDTRw#h#e#1Euk&,Yw+Ap"PIZ*j*Ug">m>|ڇ(#FXzCi9%J'H3Xwi-9s0S`R^֮ YLJz+q^i}i1jLK+ [ NzDSq[+Q'ݖl=s<[iIWz=%}[jɁ֠$$N7IUm83SVŭw)#0$g C26^ʓW<=B>{R)&繻8j3cbbce7TE1r\'}FūLO+KʢXm/=H 6FaRHI^Lȹ83g9CM93쑑nE)=q4I$s'ݠajm]"O>L4Vb;(eHm$֫ӆyYtYYr(<Ɠ2Fm "f֒;Tξu8jZR$b!E*9 yy+V:Dm Œ9@-f*l2#ٿPt#T҂ӵ&;AȃWlf xϜZكfj%bs ,/uN{,Gz*kkP M6f/0[I;S)ml-؉)~q9v`ǣ4gZJ}h&dﺥ#{}uDa7j(I'2OҒMF7 .Ey<$5;2ժTI %)TwG54Ŭ Kb6rG;uq\[8DJ'i$?Pq-ݗs\JGkYO2%}b\9;Tk⾜3%qSd( [O4i'jQՃ &F Ҧ T2!G{N j~:Cz J3|xd(6TZ a b5gfK\I)WYARA(RVE$G8at̖qWq{B:Q^g3QzcAZrH|GMcjb{+)r=>:de:¹[QOe@>ISP1nIq!:3G).!ŶB꠲#0Eb2"Lt4ƺKCGn9P=PeoX8@fղ Gi9k ^aHAV<)GG*k_aUΜWsX4ʷ\%m,W*F}<1E/&NJIʳ:PmeRuń%A<ᶧ2s^s-9$PHw]ZB#[>9Fm*>Ut.HugK9uaAF.%fW&J~$k^S:iގT9_5`_bR`ܒ(8Fa?jMc4Pŭ!VB7 W+߀ i>b٠,]?<{aXgpJ]璹نrV53-)p:,R%>#W۲4K{%L%]ͅP,7"[NI:ܴ- AJr)#"=k#Eoa PP$C>7m_t ڠcJZymA [qwDw|*3(FMۭ\KP-'1WK, suu;~ZaTnyi$A =46i֑AUU"l:gA ]"8&ד<{z&O!WF^XGhViWM\q(*p#Fk?p\Ym*J3B3'%jn+ IG{VcVL-f7 #/u}5bD7XMi!{#b$U]q\RGa ;OZXv^WZ\ܭ( lhSˎ6 V'h GY{49$r8AIȃ#V$HL/~l.]:>29:EkSO%N$Ϋkͯ⫝̸yˮ0mE+IVwuIu>Xj%6@[k)aqJz|؏!Υ֔RP.l@tⵅkZg'5nrqDU^kJBEBfrG)+J$"dB3#ٔk4yQCz9S\8'#/5cˑYO(4dhIM<6BߢJNDZFEgD6vnl|^kr;^hϨ1!ʌ:įZBᝋx|T+'!c t"YH=)"g6-t+.Ur$+ZzRG s*f9_QY4El>DI[}B=>v)iTg[?oWwۿlWG69k{Qx]-*$<-=W¹nUĂ}G4tZ]^Q8m!])SyR)vOR(_Aiϵei#{$hਧ.SLN}߬e}EgZwgAWPBcZÖ']P ;2/hy}1M9Fj'.ӖZy-,r ND|jlC)jqSʚV)]p3;❀[:tBH##HqhZr\j"tG-тtHtB24PJ:w;xI0$ wEQ#)FejK rSw|">Tҙ#2Xc8g,(L`S2 tM>5@<)A71iXSlHڛ9(y4KUu:xARdf5\Zq|m{ӭjI8%. ڟ5pxvqd(9P$#"8CQ NKFۘ;RTPE8^`WãRxL髍{}ġͭ緗Ҍ/<xcKOVy0\{Uk85A07)_uCuopN>~3e e޽ytYnDm3)ܠ&,![y3CcؽK+raޱX~aRbm<wE #+ԺQXfGq+h[71_A* [V٣sCEXb\fNiXNݔz NҲ wrG"+ kлYI`ϼUՄ o9Vc7^[Y"E]W>(GSkt]Gcx~hM`?WV8q w< `bJb̑ NNG[xr̈>Kþ7<7H56pIEKgoE`?4e)ޛ)7M(-4ot}LDG6"qycg~x{>8.,7W_ɦ/nG|MFU^VYpa",BBBH;GC#2JerK*ZIqbIphت݉)c繥ՅVtLnEcf62:;\Rw@{ S5Q $ϑTz;EzFO5Pn.NA<~ҌoXR|Ig$^]A|^_mmҷj8mbMbՅHmvI_MqƊFCq&Б%z>ΧKEAg4y;/0f[|@$SG,h5@0RȁцEH-qm%Kb%Dx:0XNHWIᰵ$G)|^ χ,m,#%6צIpO FDFUH5JKlI>Vxn;ĶY;dZkarnƭaeG< W#9+؄l?jEmDo<~W++0#π*<.ۘZ+H$VfF|J&#N ?*<<⢌՞\.#I: !#Sh-4'F |-[WQFH7 )d`JFCbFɞ9N9vՅW4xPOBHc2a"*90Iv5IGI<hI I*'Ƿ.-m1ȼѹKF2ٷ;*A*T6FDSKsipI tGx f$9 Ǐzf{kd@r:/?(i^b 3)_g;&IEWu̓*2t7qL Ti5, wdXr&Gwmŏy)IJD+iE:v6[=9ʰ;q` =}#q:<>~mFU631TqQ (t2/c~ iK'y˴TlxsF_$ {a8[yfc>Y͘k8&9x\Նڻ{I&7+ fv F=,ꌼcCA[c:麑î6B겦&|mFm㪈Rfw .xJês1?_UnuQGǪ?6wR5b-:q{wK  !1A2Qq"@PRa #03BCSbr4$T`c?K)o<rzѸUL<6K4F̘E¹?Q7 QZtʄSV9iE$m6vU>8_F!zaS# j_4Jzm_bȚ;/:Iq7A9Qڜp͖!QTaOSTQzqS5U{LHOWc;TWUA}YWqUNKURѾĴ:gfYnQ*dv?F6i1G6[H?W*!Wl 8OlE?U$jv<&Rا@TG"X޺51?Ikymc{TLʧA4Y+#a=[#j Ge;@֍Xًv_(uVgJjbէz;5$۱ʡ)zv|eS u̎b{ean<6\;CQ<@΍b{ZM%[*n,z{EZR++e`w޹bh9cWF2ǴU:RMWd架;UJcDtK_G@y5GāYzF 8cWb㖈qw4ecqMis,)',o=ߘq5e-0j.}xNGq?d;D5T Dbng2!zN%i`IJ4]JN Kv ./iLZFOii h=yn%wdԲ:d뉆2 ]|1jnvBV@XkxN_;J Kӯ$ΟVlXm x[0'id =qcamjdӚȹaE4rY26!۩PS#U v{-51~q<'x;Z *'Fg"pojg9l:5W媴txyyUU%`_58Mngv[+jz>XwbIt$]ɞ*{ &b^F=C4ЏZ+ F\pR]9c1b * @@K,\ϔ =0<9N{U^ozﺊ<˒D4p2 ,Ƿ˗:#]j*&*jFTܪTdF@x8׭CX2U&y({9b駴to90\DUaaƏ@J:tš#x]d0pUiJ!Џ_1Ke9s$\t%ZiW-]ZVp[!c8OڋGPmM 'ÈX$I"s)Ȍ[ڦT ׫wJsn$QӨ]dJ[;~ԕ$lŧt}7RU@&778ܷK "$4C^iQ􄆺h(Cg#P QҤ1 7~V=6~8:#7/N5qz=8ȂiEʀJpnx8.9@~1m3sE? :zqGY}:O#yw23$1%m}8`E毑s_PznQ[LF%D;S)י -YW < quTݪҒl>I£$qG,Ȑf=g + `~}m5dO+ipyOfv]ishu*8tx"4n7putfV]D`i=ZHWIwȩ<[.P\xӊF)jbKfzASi{*u#8 9p뚰 H@ff>,`2 L6b8 mw{Hn3|b3Fg1e6C<eH /_~B#L *t0xbS% 웞: Aɔ89hjd[OY墪9sŎzNZ:&Yiu%MGw=Y ]QӍ -u@'p[wK%suԘse^wbiɫ:f䲯4ֶCP JFE32 X;yVeAbFyyX%H ,vgb~Ksʊ&V φ 5f̅2K7ZVԎBLǑ=zv-yq,nȇ'(:8$(rH*!S RI.Lj"9\W>])|›\o?-tEs#678PI:e5n$i0ScudA F(ET lq{讬3 28xۆ1IPԲ v0r$0{[J*cyA 1OQ-3f5;׆!`;mV[g{*d$221VR8jk.aH)7c=BO>~ T77XӇʧ _NاVV:Gye)NKk Ǵ`ՏS=Wy\cu`}@8C2su XqC Պ̜xEU ڭ{$KόI@F؛NLOA$F[X2rĔG L\wE2J3S8IJ2e`A7),b +noĐ<{XA"Lj%W̮RI7=e0O {F 3t6ǽN7aNHmo!_5G/GGz`ǻwl${wzd2X,!a/@X{wh]S MARIJUANA
— DIOS — NO — CREA — NADA — EN — VANO —
©TheAlmightyZeus
# Xmethods for libstdc++. # Copyright (C) 2014-2020 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import gdb import gdb.xmethod import re matcher_name_prefix = 'libstdc++::' def get_bool_type(): return gdb.lookup_type('bool') def get_std_size_type(): return gdb.lookup_type('std::size_t') class LibStdCxxXMethod(gdb.xmethod.XMethod): def __init__(self, name, worker_class): gdb.xmethod.XMethod.__init__(self, name) self.worker_class = worker_class # Xmethods for std::array class ArrayWorkerBase(gdb.xmethod.XMethodWorker): def __init__(self, val_type, size): self._val_type = val_type self._size = size def null_value(self): nullptr = gdb.parse_and_eval('(void *) 0') return nullptr.cast(self._val_type.pointer()).dereference() class ArraySizeWorker(ArrayWorkerBase): def __init__(self, val_type, size): ArrayWorkerBase.__init__(self, val_type, size) def get_arg_types(self): return None def get_result_type(self, obj): return get_std_size_type() def __call__(self, obj): return self._size class ArrayEmptyWorker(ArrayWorkerBase): def __init__(self, val_type, size): ArrayWorkerBase.__init__(self, val_type, size) def get_arg_types(self): return None def get_result_type(self, obj): return get_bool_type() def __call__(self, obj): return (int(self._size) == 0) class ArrayFrontWorker(ArrayWorkerBase): def __init__(self, val_type, size): ArrayWorkerBase.__init__(self, val_type, size) def get_arg_types(self): return None def get_result_type(self, obj): return self._val_type def __call__(self, obj): if int(self._size) > 0: return obj['_M_elems'][0] else: return self.null_value() class ArrayBackWorker(ArrayWorkerBase): def __init__(self, val_type, size): ArrayWorkerBase.__init__(self, val_type, size) def get_arg_types(self): return None def get_result_type(self, obj): return self._val_type def __call__(self, obj): if int(self._size) > 0: return obj['_M_elems'][self._size - 1] else: return self.null_value() class ArrayAtWorker(ArrayWorkerBase): def __init__(self, val_type, size): ArrayWorkerBase.__init__(self, val_type, size) def get_arg_types(self): return get_std_size_type() def get_result_type(self, obj, index): return self._val_type def __call__(self, obj, index): if int(index) >= int(self._size): raise IndexError('Array index "%d" should not be >= %d.' % ((int(index), self._size))) return obj['_M_elems'][index] class ArraySubscriptWorker(ArrayWorkerBase): def __init__(self, val_type, size): ArrayWorkerBase.__init__(self, val_type, size) def get_arg_types(self): return get_std_size_type() def get_result_type(self, obj, index): return self._val_type def __call__(self, obj, index): if int(self._size) > 0: return obj['_M_elems'][index] else: return self.null_value() class ArrayMethodsMatcher(gdb.xmethod.XMethodMatcher): def __init__(self): gdb.xmethod.XMethodMatcher.__init__(self, matcher_name_prefix + 'array') self._method_dict = { 'size': LibStdCxxXMethod('size', ArraySizeWorker), 'empty': LibStdCxxXMethod('empty', ArrayEmptyWorker), 'front': LibStdCxxXMethod('front', ArrayFrontWorker), 'back': LibStdCxxXMethod('back', ArrayBackWorker), 'at': LibStdCxxXMethod('at', ArrayAtWorker), 'operator[]': LibStdCxxXMethod('operator[]', ArraySubscriptWorker), } self.methods = [self._method_dict[m] for m in self._method_dict] def match(self, class_type, method_name): if not re.match('^std::(__\d+::)?array<.*>$', class_type.tag): return None method = self._method_dict.get(method_name) if method is None or not method.enabled: return None try: value_type = class_type.template_argument(0) size = class_type.template_argument(1) except: return None return method.worker_class(value_type, size) # Xmethods for std::deque class DequeWorkerBase(gdb.xmethod.XMethodWorker): def __init__(self, val_type): self._val_type = val_type self._bufsize = 512 // val_type.sizeof or 1 def size(self, obj): first_node = obj['_M_impl']['_M_start']['_M_node'] last_node = obj['_M_impl']['_M_finish']['_M_node'] cur = obj['_M_impl']['_M_finish']['_M_cur'] first = obj['_M_impl']['_M_finish']['_M_first'] return (last_node - first_node) * self._bufsize + (cur - first) def index(self, obj, idx): first_node = obj['_M_impl']['_M_start']['_M_node'] index_node = first_node + int(idx) // self._bufsize return index_node[0][idx % self._bufsize] class DequeEmptyWorker(DequeWorkerBase): def get_arg_types(self): return None def get_result_type(self, obj): return get_bool_type() def __call__(self, obj): return (obj['_M_impl']['_M_start']['_M_cur'] == obj['_M_impl']['_M_finish']['_M_cur']) class DequeSizeWorker(DequeWorkerBase): def get_arg_types(self): return None def get_result_type(self, obj): return get_std_size_type() def __call__(self, obj): return self.size(obj) class DequeFrontWorker(DequeWorkerBase): def get_arg_types(self): return None def get_result_type(self, obj): return self._val_type def __call__(self, obj): return obj['_M_impl']['_M_start']['_M_cur'][0] class DequeBackWorker(DequeWorkerBase): def get_arg_types(self): return None def get_result_type(self, obj): return self._val_type def __call__(self, obj): if (obj['_M_impl']['_M_finish']['_M_cur'] == obj['_M_impl']['_M_finish']['_M_first']): prev_node = obj['_M_impl']['_M_finish']['_M_node'] - 1 return prev_node[0][self._bufsize - 1] else: return obj['_M_impl']['_M_finish']['_M_cur'][-1] class DequeSubscriptWorker(DequeWorkerBase): def get_arg_types(self): return get_std_size_type() def get_result_type(self, obj, subscript): return self._val_type def __call__(self, obj, subscript): return self.index(obj, subscript) class DequeAtWorker(DequeWorkerBase): def get_arg_types(self): return get_std_size_type() def get_result_type(self, obj, index): return self._val_type def __call__(self, obj, index): deque_size = int(self.size(obj)) if int(index) >= deque_size: raise IndexError('Deque index "%d" should not be >= %d.' % (int(index), deque_size)) else: return self.index(obj, index) class DequeMethodsMatcher(gdb.xmethod.XMethodMatcher): def __init__(self): gdb.xmethod.XMethodMatcher.__init__(self, matcher_name_prefix + 'deque') self._method_dict = { 'empty': LibStdCxxXMethod('empty', DequeEmptyWorker), 'size': LibStdCxxXMethod('size', DequeSizeWorker), 'front': LibStdCxxXMethod('front', DequeFrontWorker), 'back': LibStdCxxXMethod('back', DequeBackWorker), 'operator[]': LibStdCxxXMethod('operator[]', DequeSubscriptWorker), 'at': LibStdCxxXMethod('at', DequeAtWorker) } self.methods = [self._method_dict[m] for m in self._method_dict] def match(self, class_type, method_name): if not re.match('^std::(__\d+::)?deque<.*>$', class_type.tag): return None method = self._method_dict.get(method_name) if method is None or not method.enabled: return None return method.worker_class(class_type.template_argument(0)) # Xmethods for std::forward_list class ForwardListWorkerBase(gdb.xmethod.XMethodMatcher): def __init__(self, val_type, node_type): self._val_type = val_type self._node_type = node_type def get_arg_types(self): return None class ForwardListEmptyWorker(ForwardListWorkerBase): def get_result_type(self, obj): return get_bool_type() def __call__(self, obj): return obj['_M_impl']['_M_head']['_M_next'] == 0 class ForwardListFrontWorker(ForwardListWorkerBase): def get_result_type(self, obj): return self._val_type def __call__(self, obj): node = obj['_M_impl']['_M_head']['_M_next'].cast(self._node_type) val_address = node['_M_storage']['_M_storage'].address return val_address.cast(self._val_type.pointer()).dereference() class ForwardListMethodsMatcher(gdb.xmethod.XMethodMatcher): def __init__(self): matcher_name = matcher_name_prefix + 'forward_list' gdb.xmethod.XMethodMatcher.__init__(self, matcher_name) self._method_dict = { 'empty': LibStdCxxXMethod('empty', ForwardListEmptyWorker), 'front': LibStdCxxXMethod('front', ForwardListFrontWorker) } self.methods = [self._method_dict[m] for m in self._method_dict] def match(self, class_type, method_name): if not re.match('^std::(__\d+::)?forward_list<.*>$', class_type.tag): return None method = self._method_dict.get(method_name) if method is None or not method.enabled: return None val_type = class_type.template_argument(0) node_type = gdb.lookup_type(str(class_type) + '::_Node').pointer() return method.worker_class(val_type, node_type) # Xmethods for std::list class ListWorkerBase(gdb.xmethod.XMethodWorker): def __init__(self, val_type, node_type): self._val_type = val_type self._node_type = node_type def get_arg_types(self): return None def get_value_from_node(self, node): node = node.dereference() if node.type.fields()[1].name == '_M_data': # C++03 implementation, node contains the value as a member return node['_M_data'] # C++11 implementation, node stores value in __aligned_membuf addr = node['_M_storage'].address return addr.cast(self._val_type.pointer()).dereference() class ListEmptyWorker(ListWorkerBase): def get_result_type(self, obj): return get_bool_type() def __call__(self, obj): base_node = obj['_M_impl']['_M_node'] if base_node['_M_next'] == base_node.address: return True else: return False class ListSizeWorker(ListWorkerBase): def get_result_type(self, obj): return get_std_size_type() def __call__(self, obj): begin_node = obj['_M_impl']['_M_node']['_M_next'] end_node = obj['_M_impl']['_M_node'].address size = 0 while begin_node != end_node: begin_node = begin_node['_M_next'] size += 1 return size class ListFrontWorker(ListWorkerBase): def get_result_type(self, obj): return self._val_type def __call__(self, obj): node = obj['_M_impl']['_M_node']['_M_next'].cast(self._node_type) return self.get_value_from_node(node) class ListBackWorker(ListWorkerBase): def get_result_type(self, obj): return self._val_type def __call__(self, obj): prev_node = obj['_M_impl']['_M_node']['_M_prev'].cast(self._node_type) return self.get_value_from_node(prev_node) class ListMethodsMatcher(gdb.xmethod.XMethodMatcher): def __init__(self): gdb.xmethod.XMethodMatcher.__init__(self, matcher_name_prefix + 'list') self._method_dict = { 'empty': LibStdCxxXMethod('empty', ListEmptyWorker), 'size': LibStdCxxXMethod('size', ListSizeWorker), 'front': LibStdCxxXMethod('front', ListFrontWorker), 'back': LibStdCxxXMethod('back', ListBackWorker) } self.methods = [self._method_dict[m] for m in self._method_dict] def match(self, class_type, method_name): if not re.match('^std::(__\d+::)?(__cxx11::)?list<.*>$', class_type.tag): return None method = self._method_dict.get(method_name) if method is None or not method.enabled: return None val_type = class_type.template_argument(0) node_type = gdb.lookup_type(str(class_type) + '::_Node').pointer() return method.worker_class(val_type, node_type) # Xmethods for std::vector class VectorWorkerBase(gdb.xmethod.XMethodWorker): def __init__(self, val_type): self._val_type = val_type def size(self, obj): if self._val_type.code == gdb.TYPE_CODE_BOOL: start = obj['_M_impl']['_M_start']['_M_p'] finish = obj['_M_impl']['_M_finish']['_M_p'] finish_offset = obj['_M_impl']['_M_finish']['_M_offset'] bit_size = start.dereference().type.sizeof * 8 return (finish - start) * bit_size + finish_offset else: return obj['_M_impl']['_M_finish'] - obj['_M_impl']['_M_start'] def get(self, obj, index): if self._val_type.code == gdb.TYPE_CODE_BOOL: start = obj['_M_impl']['_M_start']['_M_p'] bit_size = start.dereference().type.sizeof * 8 valp = start + index // bit_size offset = index % bit_size return (valp.dereference() & (1 << offset)) > 0 else: return obj['_M_impl']['_M_start'][index] class VectorEmptyWorker(VectorWorkerBase): def get_arg_types(self): return None def get_result_type(self, obj): return get_bool_type() def __call__(self, obj): return int(self.size(obj)) == 0 class VectorSizeWorker(VectorWorkerBase): def get_arg_types(self): return None def get_result_type(self, obj): return get_std_size_type() def __call__(self, obj): return self.size(obj) class VectorFrontWorker(VectorWorkerBase): def get_arg_types(self): return None def get_result_type(self, obj): return self._val_type def __call__(self, obj): return self.get(obj, 0) class VectorBackWorker(VectorWorkerBase): def get_arg_types(self): return None def get_result_type(self, obj): return self._val_type def __call__(self, obj): return self.get(obj, int(self.size(obj)) - 1) class VectorAtWorker(VectorWorkerBase): def get_arg_types(self): return get_std_size_type() def get_result_type(self, obj, index): return self._val_type def __call__(self, obj, index): size = int(self.size(obj)) if int(index) >= size: raise IndexError('Vector index "%d" should not be >= %d.' % ((int(index), size))) return self.get(obj, int(index)) class VectorSubscriptWorker(VectorWorkerBase): def get_arg_types(self): return get_std_size_type() def get_result_type(self, obj, subscript): return self._val_type def __call__(self, obj, subscript): return self.get(obj, int(subscript)) class VectorMethodsMatcher(gdb.xmethod.XMethodMatcher): def __init__(self): gdb.xmethod.XMethodMatcher.__init__(self, matcher_name_prefix + 'vector') self._method_dict = { 'size': LibStdCxxXMethod('size', VectorSizeWorker), 'empty': LibStdCxxXMethod('empty', VectorEmptyWorker), 'front': LibStdCxxXMethod('front', VectorFrontWorker), 'back': LibStdCxxXMethod('back', VectorBackWorker), 'at': LibStdCxxXMethod('at', VectorAtWorker), 'operator[]': LibStdCxxXMethod('operator[]', VectorSubscriptWorker), } self.methods = [self._method_dict[m] for m in self._method_dict] def match(self, class_type, method_name): if not re.match('^std::(__\d+::)?vector<.*>$', class_type.tag): return None method = self._method_dict.get(method_name) if method is None or not method.enabled: return None return method.worker_class(class_type.template_argument(0)) # Xmethods for associative containers class AssociativeContainerWorkerBase(gdb.xmethod.XMethodWorker): def __init__(self, unordered): self._unordered = unordered def node_count(self, obj): if self._unordered: return obj['_M_h']['_M_element_count'] else: return obj['_M_t']['_M_impl']['_M_node_count'] def get_arg_types(self): return None class AssociativeContainerEmptyWorker(AssociativeContainerWorkerBase): def get_result_type(self, obj): return get_bool_type() def __call__(self, obj): return int(self.node_count(obj)) == 0 class AssociativeContainerSizeWorker(AssociativeContainerWorkerBase): def get_result_type(self, obj): return get_std_size_type() def __call__(self, obj): return self.node_count(obj) class AssociativeContainerMethodsMatcher(gdb.xmethod.XMethodMatcher): def __init__(self, name): gdb.xmethod.XMethodMatcher.__init__(self, matcher_name_prefix + name) self._name = name self._method_dict = { 'size': LibStdCxxXMethod('size', AssociativeContainerSizeWorker), 'empty': LibStdCxxXMethod('empty', AssociativeContainerEmptyWorker), } self.methods = [self._method_dict[m] for m in self._method_dict] def match(self, class_type, method_name): if not re.match('^std::(__\d+::)?%s<.*>$' % self._name, class_type.tag): return None method = self._method_dict.get(method_name) if method is None or not method.enabled: return None unordered = 'unordered' in self._name return method.worker_class(unordered) # Xmethods for std::unique_ptr class UniquePtrGetWorker(gdb.xmethod.XMethodWorker): "Implements std::unique_ptr::get() and std::unique_ptr::operator->()" def __init__(self, elem_type): self._is_array = elem_type.code == gdb.TYPE_CODE_ARRAY if self._is_array: self._elem_type = elem_type.target() else: self._elem_type = elem_type def get_arg_types(self): return None def get_result_type(self, obj): return self._elem_type.pointer() def _supports(self, method_name): "operator-> is not supported for unique_ptr" return method_name == 'get' or not self._is_array def __call__(self, obj): impl_type = obj.dereference().type.fields()[0].type.tag # Check for new implementations first: if re.match('^std::(__\d+::)?__uniq_ptr_(data|impl)<.*>$', impl_type): tuple_member = obj['_M_t']['_M_t'] elif re.match('^std::(__\d+::)?tuple<.*>$', impl_type): tuple_member = obj['_M_t'] else: return None tuple_impl_type = tuple_member.type.fields()[0].type # _Tuple_impl tuple_head_type = tuple_impl_type.fields()[1].type # _Head_base head_field = tuple_head_type.fields()[0] if head_field.name == '_M_head_impl': return tuple_member['_M_head_impl'] elif head_field.is_base_class: return tuple_member.cast(head_field.type) else: return None class UniquePtrDerefWorker(UniquePtrGetWorker): "Implements std::unique_ptr::operator*()" def __init__(self, elem_type): UniquePtrGetWorker.__init__(self, elem_type) def get_result_type(self, obj): return self._elem_type def _supports(self, method_name): "operator* is not supported for unique_ptr" return not self._is_array def __call__(self, obj): return UniquePtrGetWorker.__call__(self, obj).dereference() class UniquePtrSubscriptWorker(UniquePtrGetWorker): "Implements std::unique_ptr::operator[](size_t)" def __init__(self, elem_type): UniquePtrGetWorker.__init__(self, elem_type) def get_arg_types(self): return get_std_size_type() def get_result_type(self, obj, index): return self._elem_type def _supports(self, method_name): "operator[] is only supported for unique_ptr" return self._is_array def __call__(self, obj, index): return UniquePtrGetWorker.__call__(self, obj)[index] class UniquePtrMethodsMatcher(gdb.xmethod.XMethodMatcher): def __init__(self): gdb.xmethod.XMethodMatcher.__init__(self, matcher_name_prefix + 'unique_ptr') self._method_dict = { 'get': LibStdCxxXMethod('get', UniquePtrGetWorker), 'operator->': LibStdCxxXMethod('operator->', UniquePtrGetWorker), 'operator*': LibStdCxxXMethod('operator*', UniquePtrDerefWorker), 'operator[]': LibStdCxxXMethod('operator[]', UniquePtrSubscriptWorker), } self.methods = [self._method_dict[m] for m in self._method_dict] def match(self, class_type, method_name): if not re.match('^std::(__\d+::)?unique_ptr<.*>$', class_type.tag): return None method = self._method_dict.get(method_name) if method is None or not method.enabled: return None worker = method.worker_class(class_type.template_argument(0)) if worker._supports(method_name): return worker return None # Xmethods for std::shared_ptr class SharedPtrGetWorker(gdb.xmethod.XMethodWorker): "Implements std::shared_ptr::get() and std::shared_ptr::operator->()" def __init__(self, elem_type): self._is_array = elem_type.code == gdb.TYPE_CODE_ARRAY if self._is_array: self._elem_type = elem_type.target() else: self._elem_type = elem_type def get_arg_types(self): return None def get_result_type(self, obj): return self._elem_type.pointer() def _supports(self, method_name): "operator-> is not supported for shared_ptr" return method_name == 'get' or not self._is_array def __call__(self, obj): return obj['_M_ptr'] class SharedPtrDerefWorker(SharedPtrGetWorker): "Implements std::shared_ptr::operator*()" def __init__(self, elem_type): SharedPtrGetWorker.__init__(self, elem_type) def get_result_type(self, obj): return self._elem_type def _supports(self, method_name): "operator* is not supported for shared_ptr" return not self._is_array def __call__(self, obj): return SharedPtrGetWorker.__call__(self, obj).dereference() class SharedPtrSubscriptWorker(SharedPtrGetWorker): "Implements std::shared_ptr::operator[](size_t)" def __init__(self, elem_type): SharedPtrGetWorker.__init__(self, elem_type) def get_arg_types(self): return get_std_size_type() def get_result_type(self, obj, index): return self._elem_type def _supports(self, method_name): "operator[] is only supported for shared_ptr" return self._is_array def __call__(self, obj, index): # Check bounds if _elem_type is an array of known bound m = re.match('.*\[(\d+)]$', str(self._elem_type)) if m and index >= int(m.group(1)): raise IndexError('shared_ptr<%s> index "%d" should not be >= %d.' % (self._elem_type, int(index), int(m.group(1)))) return SharedPtrGetWorker.__call__(self, obj)[index] class SharedPtrUseCountWorker(gdb.xmethod.XMethodWorker): "Implements std::shared_ptr::use_count()" def __init__(self, elem_type): SharedPtrUseCountWorker.__init__(self, elem_type) def get_arg_types(self): return None def get_result_type(self, obj): return gdb.lookup_type('long') def __call__(self, obj): refcounts = obj['_M_refcount']['_M_pi'] return refcounts['_M_use_count'] if refcounts else 0 class SharedPtrUniqueWorker(SharedPtrUseCountWorker): "Implements std::shared_ptr::unique()" def __init__(self, elem_type): SharedPtrUseCountWorker.__init__(self, elem_type) def get_result_type(self, obj): return gdb.lookup_type('bool') def __call__(self, obj): return SharedPtrUseCountWorker.__call__(self, obj) == 1 class SharedPtrMethodsMatcher(gdb.xmethod.XMethodMatcher): def __init__(self): gdb.xmethod.XMethodMatcher.__init__(self, matcher_name_prefix + 'shared_ptr') self._method_dict = { 'get': LibStdCxxXMethod('get', SharedPtrGetWorker), 'operator->': LibStdCxxXMethod('operator->', SharedPtrGetWorker), 'operator*': LibStdCxxXMethod('operator*', SharedPtrDerefWorker), 'operator[]': LibStdCxxXMethod('operator[]', SharedPtrSubscriptWorker), 'use_count': LibStdCxxXMethod('use_count', SharedPtrUseCountWorker), 'unique': LibStdCxxXMethod('unique', SharedPtrUniqueWorker), } self.methods = [self._method_dict[m] for m in self._method_dict] def match(self, class_type, method_name): if not re.match('^std::(__\d+::)?shared_ptr<.*>$', class_type.tag): return None method = self._method_dict.get(method_name) if method is None or not method.enabled: return None worker = method.worker_class(class_type.template_argument(0)) if worker._supports(method_name): return worker return None def register_libstdcxx_xmethods(locus): gdb.xmethod.register_xmethod_matcher(locus, ArrayMethodsMatcher()) gdb.xmethod.register_xmethod_matcher(locus, ForwardListMethodsMatcher()) gdb.xmethod.register_xmethod_matcher(locus, DequeMethodsMatcher()) gdb.xmethod.register_xmethod_matcher(locus, ListMethodsMatcher()) gdb.xmethod.register_xmethod_matcher(locus, VectorMethodsMatcher()) gdb.xmethod.register_xmethod_matcher( locus, AssociativeContainerMethodsMatcher('set')) gdb.xmethod.register_xmethod_matcher( locus, AssociativeContainerMethodsMatcher('map')) gdb.xmethod.register_xmethod_matcher( locus, AssociativeContainerMethodsMatcher('multiset')) gdb.xmethod.register_xmethod_matcher( locus, AssociativeContainerMethodsMatcher('multimap')) gdb.xmethod.register_xmethod_matcher( locus, AssociativeContainerMethodsMatcher('unordered_set')) gdb.xmethod.register_xmethod_matcher( locus, AssociativeContainerMethodsMatcher('unordered_map')) gdb.xmethod.register_xmethod_matcher( locus, AssociativeContainerMethodsMatcher('unordered_multiset')) gdb.xmethod.register_xmethod_matcher( locus, AssociativeContainerMethodsMatcher('unordered_multimap')) gdb.xmethod.register_xmethod_matcher(locus, UniquePtrMethodsMatcher()) gdb.xmethod.register_xmethod_matcher(locus, SharedPtrMethodsMatcher())