summaryrefslogtreecommitdiff
path: root/scripts/objdiff
blob: 0685bc3ce3df2737469c0e4d632c54ad70126b96 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0-only

# objdiff - a small script for validating that a commit or series of commits
# didn't change object code.
#
# Copyright 2014, Jason Cooper <jason@lakedaemon.net>
#

# usage example:
#
# $ git checkout COMMIT_A
# $ <your fancy build command here>
# $ ./scripts/objdiff record path/to/*.o
#
# $ git checkout COMMIT_B
# $ <your fancy build command here>
# $ ./scripts/objdiff record path/to/*.o
#
# $ ./scripts/objdiff diff COMMIT_A COMMIT_B
# $

# And to clean up (everything is in .objdiff/*)
# $ ./scripts/objdiff clean all
#
# Note: 'make mrproper' will also remove .objdiff

SRCTREE=$(cd $(git rev-parse --show-toplevel 2>/dev/null); pwd)

if [ -z "$SRCTREE" ]; then
	echo >&2 "ERROR: Not a git repository."
	exit 1
fi

TMPD=$SRCTREE/.objdiff

usage() {
	echo >&2 "Usage: $0 <command> <args>"
	echo >&2 "  record    <list of object files or directories>"
	echo >&2 "  diff      <commitA> <commitB>"
	echo >&2 "  clean     all | <commit>"
	exit 1
}

get_output_dir() {
	dir=${1%/*}

	if [ "$dir" = "$1" ]; then
		dir=.
	fi

	dir=$(cd $dir; pwd)

	echo $TMPD/$CMT${dir#$SRCTREE}
}

do_objdump() {
	dir=$(get_output_dir $1)
	base=${1##*/}
	stripped=$dir/${base%.o}.stripped
	dis=$dir/${base%.o}.dis

	[ ! -d "$dir" ] && mkdir -p $dir

	# remove addresses for a cleaner diff
	# http://dummdida.tumblr.com/post/60924060451/binary-diff-between-libc-from-scientificlinux-and
	$STRIP -g $1 -R __bug_table -R .note -R .comment -o $stripped
	$OBJDUMP -D $stripped | sed -e "s/^[[:space:]]\+[0-9a-f]\+//" -e "s:^$stripped:$1:" > $dis
}

dorecord() {
	[ $# -eq 0 ] && usage

	FILES="$*"

	CMT="`git rev-parse --short HEAD`"

	STRIP="${CROSS_COMPILE}strip"
	OBJDUMP="${CROSS_COMPILE}objdump"

	for d in $FILES; do
		if [ -d "$d" ]; then
			for f in $(find $d -name '*.o')
			do
				do_objdump $f
			done
		else
			do_objdump $d
		fi
	done
}

dodiff() {
	[ $# -ne 2 ] && [ $# -ne 0 ] && usage

	if [ $# -eq 0 ]; then
		SRC="`git rev-parse --short HEAD^`"
		DST="`git rev-parse --short HEAD`"
	else
		SRC="`git rev-parse --short $1`"
		DST="`git rev-parse --short $2`"
	fi

	DIFF="`which colordiff`"

	if [ ${#DIFF} -eq 0 ] || [ ! -x "$DIFF" ]; then
		DIFF="`which diff`"
	fi

	SRCD="$TMPD/$SRC"
	DSTD="$TMPD/$DST"

	if [ ! -d "$SRCD" ]; then
		echo >&2 "ERROR: $SRCD doesn't exist"
		exit 1
	fi

	if [ ! -d "$DSTD" ]; then
		echo >&2 "ERROR: $DSTD doesn't exist"
		exit 1
	fi

	$DIFF -Nurd $SRCD $DSTD
}

doclean() {
	[ $# -eq 0 ] && usage
	[ $# -gt 1 ] && usage

	if [ "x$1" = "xall" ]; then
		rm -rf $TMPD/*
	else
		CMT="`git rev-parse --short $1`"

		if [ -d "$TMPD/$CMT" ]; then
			rm -rf $TMPD/$CMT
		else
			echo >&2 "$CMT not found"
		fi
	fi
}

[ $# -eq 0 ] &&	usage

case "$1" in
	record)
		shift
		dorecord $*
		;;
	diff)
		shift
		dodiff $*
		;;
	clean)
		shift
		doclean $*
		;;
	*)
		echo >&2 "Unrecognized command '$1'"
		exit 1
		;;
esac
*ڃ^wvt>Ru];V\|ķ&&Yz8nCT_݁қ.!jH! b'|l4|I]$ w lƁJQD%4eEy3[3`SU_,~reb#:drEo1߽$; HVA`[߀` p*UCNDxl;CqfF!d -y#o;z݂*{8?P1*``8/`U^W)#eb-A#z}^J|Tv/?~WU(߷ۢuO( JP_{ BBCǵMnH~N !̓k)_>4eнz/9vNN.tsk FSJSae}ڦ1"DJ!yU>Z|9`Nތ5g]"p,nσ9po\M]hTK4vFے7$mI#mܒE% B>U5UfUf`PUUQVbvS5Qj\YT w>Rݛh]*V|;VLO.vI3\[:?svAb۲ve 0m\psS1CV`!W """I$I%ٷпgou>mT$23MߚfZ{lZY|<=Z=5-;P i?,هsa`*wZOenf/?@4 )Hhr0,W H1 pb(&:֭DhUE"6TDT5lpnί}x- Bgr*E/Y(oL s4+Ғh{Kקt^Xt/kLYH>8wn?={QyƔ;L4ېA75oîRfA>mPzKN?VWjY.Cwz^C\N I x<%3?⠋10a]gX0|ϵpj?Zt}NcP &I GtooݱCCTbA3QޟOό7ӟnP|%:O?g=W<|<LcC<lzLBOĩ$z!)yAV)f}߇ۯSh!<{@|F1< ίYǁ'༠ {_]_t4Ivz~txT_FĩDžg>1_cx:Ybk+qXX;_ب:dcf]w 2 (]Ƙ95?hߏ݁wbTbT6Y.2 8w2? Ȑ4l6y@xO׍&Ie!6Le;0UTdpQk6os!|)u#,l߉~R@s7 O5~f*<|T;'8Cd-d+E, lS_>Lmc\\uLcotLLeEÖYQ)  4zw'"/l3;o9p,?/?)ErYֽsp@ / -mĀjXn`᷑VB{!Hg=VGbOzudYG? c];m>;p}%tעgok9z ?[s:$n㑋,bF3;T?7\8_/ b,B^A 5 Ȑ6$ y`uTvb&]\CI~GӯI@D/Z vz\>5Cl{KۛdgHEE6g½!C/w}KRb[~]c)6ؾ%Oxk`~^@#|~?N/{vӝY &Øzl_`]}Qjv)ɴ.N0VHeT{=~`>6)w[CA4Ч5_u!X_a|Guï/oAmcv~# Ȕx 'ℐIg^%Ѡ.Wtl˯7w3ÚPahʝ`2Ϧڹ%)}K/z-aPQͱ {@=ΑpA q~  ?Q!F=}v|>wdpÞ܄9$! ٟ>P}7r7evwt9imxUn$-(Nan;gnrH\eOD@QߕGf}g3k&R?XZwUYF(b=Xkl6J>mلnY_~uEŷXm<|i֧u5&YhZK W z^b.ttQ"h%ezM%GMZkۭmIc8kMοkQG&',=7P@5u _a+r #{otB~+=~G=e'g?8Kf(R'@ |:z:-f\L.v*'_}d%=̼}v)Qw_ug*[?c5D 5svB|0-d`'v -Vb:~~w8rܘ{T'rvF Wk`Q"96Rg<:q-s̜>,ve2ՋZ 2;TMUauwQ2Q l$:&@dq;z&-0McaҤ(DN]D\!!Zql@ I C6hZjDc #g''DUd9G ŸTAS .ߗ]ҬroL.8c/v6g*,UHl=l溹Zyg~4oG?Q;:ugJ eH,;dtu؂ tKS[)KmSgo~{<(*}* -㿻 = s_c\uwt;قrƒGl-GaY6e+tvKst~GǢ,ó!<|wJ'IjxA,s3ˠ::AT+`uGKҏzb0uoZc'].Vmr?bcaZ [Whgj`+sߪ=<%Ap'_z$.rk%2Bk6ݘkSzRVKjϢ;ݓb&'eK[v3ց`@PPrpW'R}I^kH(F&yqa: YHaU "VD\_iB!U)rfP={IAEUjkR-$i`WxuUn#|B/y z Y{4nH Ŵ!a HZHPo3O+áv2 &f%N]9J (kdS|CeG n2M i4jGQnCL90q 8î8G80Ļȼ"SBFU4lC Ǔ*cChaMz5z2mJ:inqAqszESo1peɔWS82=6AF[ D 5[ j2f.ii'sWUn9E>IbB5$gρ vvwX/49@lFJ+' NU6wkK.˭lUu XBtٍzIDw`~1YhRy{͠Bm",rY؆un3ۢMb0G4srYPsQNeBD&@4H mFtZ7oqh q CR~4ڀpIg!UTH]R `1N]1xN1c;zMAטl(9:l!̰zN H_?I G_X`Dzcld|cOsS5;7T9f i?NʪHxR{>VvE}ӭiPF/f=~lR)zkOaWJQh pQ^`?OUQL/>_lHlE^-v u>7vNX] cma+|&fǤ@{h w zi泙d :^Kq:wpLsyt*>v,L˾t5paK6y$4ȋJf]~o3PCVkN~Ӝ{Ǒ8l QEd7 IR5%qd[ f.~/.=ҽť@|4P]d]42J2aB)=s6HOw{~cbୌl¢(XcT@j2t?&%ğǫ>oa=/@@ce5wѵMBg%Q,c!z[saW90@O'MEQjKwPIzBP$7CB=3T=:WC'y7˃pׇ<x m dGm C,\Sqˈ֘UTjfǿqTqPrk/y U6p;|ΖD KgHX򬃝^#;a}oSka0!@|;ԏLp$J3tk|TwH8'Q]ruNjUO2)C܃_j. T <.M'c2z]mDaf}jyj3h<YVS^W9~ԴgFv g0"5LWF0vԄS_Τ?=rv}.nGȩEXzn~2:t? 3Z% Wc;%[=[{~] 5BN̵j޻z^m\ëޯ#OGNQ=r8fm1kla'ҽ24&C~.qeK-}oz@q}^;o0+o,!S >u-;ˌe6/HC]-怱}y,,p2 qxOŋ!|p^OwuM͡Eu^x#Bp9;jݑ 1jm Gu҆==s)'>\{Aփ/.wM| hfe?sMq;l9揭)U3]4Fs ,{ vNsSq Aִ. *Sfn~,$#:$?K?M"sVqk46u7"\ 58rgIJӖLra'%@d&*﷚@dR }У(DU2䅺^t'|uuZu ,K#[āBJM^/p>OC|pG~R %z Ą9 ji?KuExQxX&nLAj.d G/7ݒS2Ogy OAOgkN2úΔ'wmQQChL u{+s^&#Quφs] 0وZ6%BzƖS[*YrDPxl(\ԏ6_e<˻^Hi)@zb ;f&36,Ô̗ uVIon-,ObEs(sžf2tͥ,U爝nL]K;5&6v뒶JoU2YX*c Ӡm2D77)MKf%?5J$!LrwTuI@]%!9(cg0mK_8;ͳ k$rSX#Fd`E 㒪PB \̏F8_͙Ep3Plk@ $a=~5gZmY_ 3><5w:׿lWĆ.$ a}m^l=۷-a%M5E @D.Eo9󄏦_0;1.ـXp6b,?hsF8}<#-K/|s\Er+e;{ƉErkx޺?ٔՏ _`K䰀0!{o Yv̇pd |AVpBaziSyֱqN"!B d=nߨ+԰f][9]逰2Yf7NPfTUU鴿Df } YfX |u?1>)=Mw kձ;ۭyOĻR#Eeb9{|.[1A2 wLjod R6&;B9mbw ͭ.(0PD@ZWtOJPJGnCq#oos/U/$>oTu~7n8IzuR?~GOρt7~ )RvLM'!.f`maAr\oיɲAG_{57 w"u+|$qsmל}ohBٔll] Z#BH5)p$^:I8$k6K-AoNݪ[? e$Hv]5YB\g|f7+RlU;VY uЖ9aט1E='4OScxi!"qx>ՠ9Ilx _kɜk< ˤMl1a"A~U/eus3T֋{v>ZӀu_y@s- m3AX@l_jlYJwBDy%Hl{n.:!fSZHyYʉi_b8OGt'r9;bHVNJA֐H3(zZp9wZ >QفU! hы.6Ef5f,V$d"aם%l;9-ZQJB Yi.:R7? Of`Uޜ}YoW5s!.#?c-vrrN: QX ؽd gד5Trk Q !:gd.6'QPe'# -@QllqHඤ=O}Ojٿם]̨k?Kk@?SZg% r@_4@d4v_pW)*+C;:+whk=$GpIn_qc mA/`/.oZIxB];5h814KIw0oMȳ%&IZiЌ̃1)H?8CCa"3 '1ha*ŦHB(dZx:(04(*SsQ4e+C/," 0{!]8ͨ`e;l2aScm2כE ~&`93ehu_ \_=>]djبo!-8Ļrwìml-o#0jmibH5E͙zY֐KTs„Itj;KqʇˇlGǝ󼴦 @dy [WzརY$(*Ohm,>~ K[٪ܟĒǯB|e'4h}m>fZnپv =Nt#bHy:3!]s@ է{R>w`FC+ "._ xw_';c[`8<5v9. ۂ{?[ݫQ;{;:qÝ<\;nj~0}RA& ~6' {֐c3aoWoF8^v1F"\m i {a IQ,ZD%?\5P|rEBDH1{D^w<s (Xbkc2<%Vʱ,O)`lrc_|߭p?J񻂏H$]}el4đz40T<!F5<;ɘ2qcZ#t6ӡx߲FC,n{ K֋z(BL=>|E]^uuư;gqQ\_lT? Q*"̄yS>ӭ0; ϥr7ڸ8Ly*5UBFŠ/uSx|xxiQF4=Rtn shVx76W5-++I}>-oo"`/L^ \?R8p@𜪘ѬNQ59®x}m_/>hjs"ԕG'~/{ Reû@tuW |itn[:_:er}Y5c-ۛ7"ܢdoM#+D=S{u *"^F;|z'w2a DF4q>2)gN*3(J +TxVEP 2h QMR =/E,mAs= ko]uɂ F6kKiFj$䍳[Z66σAxi_sƷ9NX8$LU`FZUe5D%kVshc,ꐊSNQ8*nYjh<'d6 RWmFl59X4ɝ.)ӋP@8>StoG sFImaÞDh;$unPX2W|!˰f_S8X<_[)M3.*njzwbY.,s߆ E۳T~jJ힥ub+,+h`z,LN6>|6#ھuEsrPȞI̎ 2!i5W˕ts8;٘b>GőP2R!0X$;0mtQTa@jڣ FT1\@td@m׿l=??gS| KD=`H5FY=h&{$-3/Q8="( 5Se1nOՂnvR:!px J1-fŒ"H.U&Owe_ 0h46َ1vuĹ.dN{&7=tb3Rfk  ܋388HC0hc1Wkӎ2RUniU:1bR`@𒱦{{>du[sM5(ЫYCdǼ? |>Z $;)'m F젖)C [ Y|C/;dR1N#&V"۫HΡDʛ `TKCU9FL_Y;0{1 "u%A=sP @ކ4iukĜ7jpch]ҁˊ`ᾌq:f Bf\(9A ";w6<1 l\1b_.F>؅]~,[}8+>2ٷ9GL/H LH <.&Os:v\0dtS4q+ *T & M(!6^~dB-֏D%f? HQKKb&zD,yf5vE隕l}^O9`0s(D0Y!{۩6o{}l0}Hiq\:;`yR"l١da{~?8¶rU{V9E&>#F=cH`Ůs T2#&ћ9a vbd.!U>{i|BS+']HwQ ^6ʈh+Ӿ3pt; w5e^\`*AT&Dxb |~[/To]R*>gJ|$h2&SgR#kJ'};0WWiY4g/`̝7w\i\z1["7we ΋`m)2[Jx YYJz}G][9gݎ1j~R7[##Q-(1?F2ӷ]'fƫOgJFr G/IO`N,feȅzhx9{wY?Kvw,.zɩoUea#8W47]#}L /U#PrXFW@{9@sx [Ǿris~ipnqA ͟)2$nY?,ӈA#+Oo;QXķtE.6Z>\3iDfǡ `|,1ǣJEHC,* 3s/}Ǜ5V ;j8"gc H#Bx_e[o~Ϧc[-;`vųe3_L~x1uBK}iCN8!R΋ =PXkD?G)e,M=/н%o9h/kiήz:S)E5G\/¤/' OC˨ݻfږ *~tFQ0 YVOe(U8Ti\rRԆmZi~ֈqk'!zhaFg |u1[PO)u *i|UͷzǫxPY-){AKf~Ne0JAKrm)УY̋Zwa8 ~X6W`g4RAu> 9L GeRLhSbcf KK2e3 ~:n8ޡ ꧓S2 1vxc?+vTi>\Bodne2!b$T~ǫbnjЖ~}cMd1s Y=yyB]!ڨ1,Yk /l(`lkF/Ssd"<{bL^AA5Ά岭YnmUSY5CspxZeH4]a6&Ʌ컪R7eUk$ƛ'-SEkQɖ2tmPګ( Y>搘:Ã⭇sgL=5t=HcD>o9PÏLm,M]tj0򜫹$j[ 9WpQ/ojku{$N vJUQed C[%s]/BY, BpX pW &7x39%h>?tZjDPoTU]G>J M A&]f<ߪ !BT>!B%|{X9lQ=2{qIcWCw>I tF$3.OIsa 5œ1`s揄ˈEBD]MfzXstD(H9HŋEv mzz * m~4e`ɵRar@_VxZrP/KzRIB&DzIsE9m:ҶLP-d,zz?]|w[;F-K =evv O+Jq?yyZZVwu+fۣSiۯInt_etɡDh}PR::S_xGFZ,sz@ ŜʮN-w߇W[?kc;v=6 \퀁H{"C9 ^sǪu^hY?Eթ˱UUG>o&u|wIxzy]575 Y͢jsRljs_&[22yI 3sE5-Ib*( l *$>U$f5:3p⿫V3ƛ{{(r!ʹY/xw?K~߸4|$~?ie k~GP}8~kۻ >Lêe'fR틨g0VEagQ]mo'2tKc ^q=ZÃ4)DPTlG}QM r@ڈ CN^1dV#UW2Izd !\ERhkl԰%Xk`ϗ̨U<@ A`hG6-̒2PxxpC1#Aj3WL)6w]=xs񩴂نE \%WV0ѳD b u{vo_X["F@kNo$ O"CȷTzi.*!+.YU3FưGr _S~ u`&};dX-y̒#UٽcA)da&,7|!41 Ԓ`I+0hR fZa [n[+Mcu[S0%^'9-}ewqIz-K%֩36Jwҳ~wiv:4s ӥ>1~}Ȇyq+̗ ۬.(B" |!EwۛF_~GK2p2 BJ ȗ;\\4jV]F9|0nC~N.?E)d$cBp[OϏYHtYSD ;0ƛ7"/H}Cfo0%f9۰@{C>S+ NP!4^W9}UaVHt1/kIldi%Q_JlM>:EvNfD `| !/:%}E7a#&>VPj'R[5B /GM %N%e'of˛zzFq6E`> Ql^;PD|5ЗsJp#/Y؊30˜nbe. W>DԯF gùg"ݥv>N-쵀}(#~H8K`D>%uپ+ȲUx y&S oa}5`O To?|#ɹVA&Plt˫3.qņi#_aX UQA %a~0L1Rrw\62:=[H` ])D}a)Qlfէ n4@ͅ)PkrH!D3Bj /@+ŧ`MvyETxBG+`>utAP/˙βuyKx ˜Pa +grzFI4?%WaهxMV!PҵV䄪%iv?  Dk-a~HG!>p#MC*f(Z@["c gqq} '"ݕ0v=ɭu-'x|60 p]:8 p -q{rԇn[2 {N[|˅Ȝ}X`@he\C,"xzw=Di>HחJyt;~=/&Fy1yU573E+lZOn k) c%*Ř^%`=j2(o]=l5WrDL|SQ5RytbhPr׎n6o 1"|DW/Fhs_7> G[Ůw4/bKv&kz/;)QbX>= ZL& PhXkQ;XQ K<+Jhx$dk +K' e$Q\ʈk9RK<#NY O=|W4O}T0 5"ͽNZm OQ92s1@߷%ON}xy*Z=0V]:(X(X4ڶ h"xE^E5 ,5+̠o=SRmsĂ.>VETȑ&YV}iw16Bg|{ 6|l;},leօP׹M,˥/jj~J89QU@F6|&C76(l^9@bT0g(!TPdoQ8f-#t Kx-IO8(Ѯp싨c1&7ʜtV,wQ8'ol3"uu%͸MFkE>D.VvKo๘(ϻxqQwa]hMJq}2fJ۞5]\8 +:qn\P-FQťe8]9ךvfOfsM -1vLHUj2v- ֛BAQH_{%T*+]\|vE.F+Gj{PWWiD\qő{.}j텂Ӂctsp }p|XuFLc7JȽ\WX^2(.ܲK03਀~VJ>Dd 8g=QOx"nwUoS.d%= NP{`THNn{c87'{4Ubdԛ 9Tׄ]R~[- -;gB\K'1z*p\*|E^9׭F&TDD7: J%t lA.pCIq$FLu1bD%šH`N}^o`[ԭc c! !(D :h1T%If5>cd.*\ZG!e'Ԯ4r9T &#A~>I(ФGh>VxaTsl[;o42˚'?0Ic_̦Afp oi|9&֕f(vxTjrߊ>JnX9R6;w{3*ZNJwf +Q^IG8 u0715k>~<9*i /9RIՄDL,2\8?t> 5UQB_ϣ (E/1K||}Wrs8~ @8#^K= ojRw(_s^ZYֺ&SQtRK{ضoW!A)&>&2^1=nN' a #6$9nNz(pX}nS>٬bɮ˕DL#@8ʨGQZoDEs+r1e6[!EܼksnsP%'սgˌg.{d_ ¡m&mR{hhf Ў%ms;wJ6Ƕ(9峸Y,\>/w qɨ: vW+!eŭ5+ )gbK E:hbw=O&/R bxܘR!Ǚf<~?ɖ~XN5v|^0S^X|69EA>{*wTV[MnTOۍ?25?˜^_Azflz$!}p٭1%x֜Qn*+ +4Rj0ЛG|Fk z!#̭W+Fu+YbBE$GVDc(РFPH{NP=sg`N4{1#; 'GJF=Z7P g4>{E8cm^6s"<^k4ޙX~쥇Y/w3{͋¬BDBU(޶8j u%/>28x?.H]BSaֱRBI?i5D9MKw^ewsϴ)R0;41FJ@§Z B#MzEnopj!d:q7Zk"4k{<8,BkFѩ1CZ$b3 F`?U\oԧ2&lgl_!)c(lK?;.3x*u1>''+e|\4D9خg}nK`NbBo74 &n~]]xŌ w2I-ΰ >A<{≘I |#寎Xk_+Y L,Drbcgf0PsEr˻! =s N>29P4$'\ݍV6_8bog7`18aT_2$Fn^w`&-N0`c2 Ԧ1jqA_0Oa;{.Q' iO^趵L\JFnQF&9&~#01n:Q嘻QNidiTE#Avx9ۇ&lBm-z7,Lv,r̡cC\yr?ZlB\#VBImmɔ-cH0O &HM:jTJ 5;ϏK f lmѷ6}) sKi+"[:~9졃候zU8LA0enkܱ-kl'JQ?at,ڲڶoc?I2ۖ;Y|sr9f0_pNݲ;:Y_v׺}e""Y6$U!J<1F2Zh̖30")cW6QBX I}lX[;ׅjV3 y-%uu;P)xqjW+#*dG ohrG0 R<۠ XXeLdcdrte XmVPE˨ȓ9UsS^)S8 Z UMcZX"" V&TZiz<ܶ@kd >k)';o,B2<@DXғF<%*7c2",ЙOȾ(!W!wwp+E Y}wtzE`8| Dz:hL׸34lD HHnMr徫235C6rQe3CyMR,(f"w] _?0-QzL?,U!|ҎO0x]Fl`6mlP(yhk|IE{bٍR(}Hƾ$S}sL5v Fa$TWv to._ Uk@â!A{1׍wW#f KI:Ð&F) ]fJ}{]jvǟHzŔ b4y._1BV s<|_07L %8.bLJaulê|xR l aw>!K~ɸJe(QCDAx ; KKcC Ԁ=2˜SۉSl9)2MWqc,*KM%+e!p xc fG;(Ht{QVf(X$b@cL 8En*a~͝]S YI2|BA37 躤?oPro}Nw!~SXWM'$(_jiﰭHKDL==AҁՙO<&KmZjhkB73? fS 1 ˭XȍEZz0/"5Vr"Gddeڈ p42!'Խ4~k=Tx&!UG?prkLa"("/h :!EB"Å]:~UP 2.@! ߒ7 'w wI9P? `useܱSD8i%wuhJT/QR(O \F<Źe,ʭpA^w[47"D>W&={,C-B#7dX$E %D/3j6U/d3hf͐&9g'xn'Kr|NŨE|UTx* |}-g_`&Uzب/*<}.kNB3Hod0p"d#m9J$jϪ1+` ,fbcz26['pg#afB.U,D윷\hW2t!Bg.r1 Ey `]3(' Af`coǡG",밞ۤzCWmjaUy)A2{˫ժǾ=mΗ`<)~B)1(;&<5r*8tzߒ%a gbeW(*/13,? ,J}%[xfjr cR-"r&Ұ5를=MGi5x2}JK#$@Aw=>#g;x4yHJk'_^T@é Agp~2Dza B"(*Qk+'}${ᱱ| Q;wLI)EW6`/Y(Agi?hhS{ϋ8P*BZ.!\0aKԅ}Tn-Z&Wݹ$fCq64M`~hJq啛%[\heH kiM؂%gL bʀ݅MAX-آ*4irt n`epg">:#DU1;6 KMwA;}C˟)UFc^,tCvL=!NXazϬ6>@r(vG 9^bY˾aQss31'n:[/}pq2dܨY Ow~ćz0nHUT6#|io1 w㘈u.1#5BW' %NH86~\oAֲ@?DN 7xI'F3>X8j`TI&ڌz3{bƥVW칚Zm^zgu§v'nhq5>,̦Ln.Z[t9]뒶9槷z\~xc1JK;6T&Έ8C3%&G;mJJ_xa+اQ{Т51" s- z +wyRx1%=F6fu}tR:qm*Fvm*Lbp妭PrR0T{-K9h:N ׃`Lcn"kn{x9+%oT_79;W#Z 5#>RIHz=L'!,x8]>i>亪ת8`geٓ/31IIRG0I"n2t䅄{_jUtaiBl#u,;BHVs+~qNƮC.}WTgwZj\ׄB#~I/nj3b9﷜$&0tq;ʩƫMpIdAcDgl.pHn}l3/QSxwА?RjXE};f#L)km.O6B| 7Gnfy+9Núg+,RRg#֊m? NSl=,^wh}2e:n|g$ Nðx:NMqy:LGZZtj8!`5u|$%C8BkhFQvJQ9In+ݣ[2zn+t/TM`95f_,kjdV,bK3G[;y4#fg.F4xY͚>C8aojnxu*K' &'7Ϩwb{xu?ѿu_ ʎ+b8jTE&貾 M$jt=Hp??[\.5džX`5t^'=C0GHW!Hu (Nv>2 }< ϣq/L6p),O#˹4X}٘FvgHV%^'p$9ilMxȞ[??6oDG&d{% Iؕ`襞dVgIUr]_2 F"*Eu3"dYYm|S$ZҬ~} L3G=O7ӀUeљ(G]z=T47EU]B`*X* `x%C q>}e3>jzX 5yg8t}Q_\ gqZuɄG~kI"73YeԐx@~Qy/rQJ\Z7G;yVp\2 _vQ  %g|ZSu#-|四uRwSGP&moT"ԛ*̙:Fl^57pƆopj\8'ӈXtZ^bO1MEőuh*ܭ,՗{$?[.hPIJh/1ЍFRQQ ٧h:lAO/%Qʆ^l'զ}U=qs xy̅aGsȖ޹^"? d÷s "+ӎ(SxXJi)GQ7'0fԀHk6r E[bVxYI&X# wVcz-(I#[\ ;8:yᝁk>1f, b2]t "hi=_(N^||գquHd5~&Vk@~dqz澧|vAtdBՕSW7?{.e1 Gge?膘r\D\S(nׁM2^RWQݏP Oh%c絜g\7^`j QMT`Z}gt "(jVp^9&=-% 0!#{~<탤)]Pdٻt@Z==po+޾JNAM3H}2؏׬WyCBV껗44{K5"KF'nVwO[Q36bpf Ը/tou*K&{}QnijYW瀏Bf[y)\ч^T ד_iEue(d2L)c;ʳ^- w'-;|l~e|6Q: ao#'_š{"D-z;V^Rś1c"J^n*iR:lǢp RԐ':SWQ `!27ǮIIR5 Bd7F~H#PHwE^ʣ.2RU,/<JRn5&)%jEfj\@ ]oل"%kIgG2j!kWU:0=W洝WԔDYm oWLڹHîS+H ާ&f.ƣ]V75\Umm49`^ ħzڱi5}@p6_d29BQEMh֤WzAR;hP  M;pkWDbd *1b2zq.aq{>IhܨEz'>˞q)&pO{^o)rW$fZ\d,zy^ 49 >n ?u}q%hcH27^Iw= eyg{_~!uiۦikW< v+ݪ/??7;ZXY]u X~Ly5p% Vt/o~NOX̓QH͖`ޠA䬛6\_Zd)D$Ű" & q@IGLqM[.+_}qO# 8Q}^Z3˞we6'Ks1h VP%XVbd@VBM{.E| spѿ}KKK&j"xL| *UKnjKT1U1Jj uXrs~^ -&礳quX#eGRxNxߍڪ|)C؛LX:,LdsY$b[=RS1ٳ)|nĄ&?Iz>ِ>gV_'/]1rp:ma a3Rc37(Ps!1kRsK-awu嚾,у!|Ӹ?$SʕZS=;qh_ Jlݨ} qa}w4vbof8~Vo"d#;t'DxN|~oNmNwRa>=yd^_QG~XWQfɾK = R?ԋwo:)}8zoղrxQ$¬90)ȟx=d}P+F!V!(%PZAԈQܰ"C2} N j"r w`'H_&]鰙͙lWֳ@d1&˒RM{|v[ng0O4P*'*{F&F# >'/#݇b`R뀢du~苪 ϥ@?m#ICKa/'g8Lmp_խ|/aX0ʥ{o>e/Oau?[k8z?p!@|WUCBxҒL@"04whOife#ٲJ5?~͎vԑ6!dQeP, (OOcTrAR0EA?\xF `R@vڼ5B?7Eb`xoWw˅-wǟ>aG.1Kݥ}]Q-: uö6mw7:3-tAw[~uhKр~}v~}rxP9vO/<7Ǘ>q_1mg 26[Dyھ>,9-fAV< u)~uzlH@kixs`̿g7/2'#&h(:̨#! V+X(;(S0i#pџvMa~|?vajf&G/oPq@mvzJ#؏vͮ&l>th!!Fx刈E:u!::A$C} #=NH焆?[?]a[6-eLA61PhtvJ~0r @5jO(@.GXH]WT妭[_ OidYfh"]EAs٦J*!P .\퐿 PԝjyHŊX^ ߭eMCKJ[=} 򟮑Uw֟g2zPY)8\'&Ɩ @^HVz|7; ݘpavGQ ›ã>qcY#Wkշ>}kZGwg]Ͼ3mRkFIRέAoKzlmzQ <\Fu1~,Qc3v>p>;kz]O!m؞ F a/,WV?نph\~rܱ9);LBul^Ed'9 YwW:FDDKOwEifbd_G{MWWƮHK|]֯"+xG_¾]jJU ,>U'*zgnR{ؾ[ˠc~!ptdtc4c7 .`Rd/un~;qCFPwn y\`xjf]73&qq¬Mشr_t!2v1De.ѳ#3jvF^TwiԍN|E<0<ϏPkA,1si|謨6( NQbS1 O! AY~]+O[ُOf>Bm"V0.f)T3¯Um~، >9r5 $j9~=قbEQ lW/Y&哂0%~^{c5gqmFީxv|ѿ1yG^`IoݍڡmTU2xMLM PI\PLw2?>=~Jɢu r5MENWq w 9}}?z0Y3]cW]M9 M>?x|\zGNHN9 /,-:-D9dPCt.ю2s1}'0(^Df$lPRVTp1X=@_/@]gRDjn2YNqMmuHe`B@5AlaڿtؐN(M~Yg%ANH߻~w_ոP(ׂDLGq]n'F6s~Oz~XNd\0wCPr?SBܵRSƳj)$J4J"8N;Խo[[kj>JvoThI\# b! YO/ c~W*\ QC鮖H-Wiv@ Ӓs\IN{#jKR) E{Yd;xj5/Y8,~ ͱbo1rvbds4b2K4eyVES Sn^ؚ̖I%Jj`QjV+\VH%֠ 5@D?-Ȅ"H -v%vq_ LGéGyfIjgFM r+#uaf;m5LCRN@H !=jÏ ĄV慨'#2dIF 5dkdh0`≯~3dvudXLr0_8}H ߒR tyCށ.yu|'2c cy $ȉ`m\3IvZ?jz0KPO#()b;gWyo߫ߢwbx˘G ti3T]0~݋Ń~IC@@JJt כֿuw5PRA|sE M.lHz^3A#(J\(a_C>o{z樶K v|h&Dh#GZ5e1~,V'T`2'&$|,zmqakkeI H\Emsx~L7!l\`wY FvjڕsTW&k=@uї`̈́hA,F> c:I:[~E~h92Tyyl5\:vA]WcBwY4[ܽjtNFGm?ct]GA$8sr̪Y;.T ki`UXP$^; [e&0wr֭>{#U B':$%UqέHL+s !^KZhBHz9hm/tLqڱ,,]U^նV;g|*ɧnOI7 SӞj(gFJ``(:9/7wDo-'nGGsQԨJۛ&!`Z--':2"I FEB*$Ɯ"%gp{ v}0tQF-!~-+G߻s lngWh(dU e(l8jO3ڸsBhŋ'ckܜqai~E۟m+hda\43 Hui8!V%3%)5(Þ$!ܘ6[ 3vgLonAȲO{/`lLM&c3A,:iXa k*R9vQ"SK1r%v6ʃBWnBv ?S#ƅG\9WI$@7}z1!Yf;5:jK$'툁;SaW1@ ANsOIV`;'syEs2lsn0aX, +E3'kQns_H1'Mw2,s[^ 1 J)[#SO 'IXv:6`~~5L]\9|KE^ xW){c פD6T6!w,NLBj¿G; XP}[+oe09rEQħ ݤ=۲6L[{H& Y/s~ 7Wù)62U (k6`wz(8އ udY]Ek̮}Re(.#L^s"ڵ/6):yϦ&}>9Y{JnYPQwipgL@:⬮g K('ye)_xR4YsSmBo\c|Pv"d0[0IVZ9+ݼwǥ·٪`Try`IcŢmp#`>z=^c+\9ЉX8ug痸LlX ^h x-(#d"H7&*!n{U ?Kݗngr ?o$& ``W-K5͖o_ 0ZDO@|l,΃W͎ CJp6$,yFg$# m؀>ST!Pk$Lc1g$0\0#xÍ&6 "rZ Í-Sِ6ZnX X>K0Q7R; d(1lŦ? |I֎.bc ݼ*\6d9閏9'Sp=^Xax @C`qiF N|䴱W5O@RvO<j5yiG-˅g5/^~=m~]notoyz~( $R߼G~φBG+s5.'ٟpA!$FpI>CYvehŖCupUlFc4笢~sC76 B!~)yֶ>`ܚD=锰kmsqGx֨7 >lI@R:=̤ȽFPu֥;pQkry?#Yg-Cةټ fRwy/nk/Z$kZ~L\&딚BA%%vniN.}!n@VBleiRDmN&cڮs`05~Siߎ!s>y4s(OЃޘGV /K]-#HOGE@Z5Hr"!܁&9e'j)ԕ]g<(ݣȚLsg 4i<;>=|3@FW+Π;˘-s z$n}.{3i׺s;2& ci./[=c߇^!uËڐG1,:ʹmEްˉϪ.$)vvHpDFcgiO0ZEd+HP$ǘSr'-fFFT.FNBaS !ր^w5f&W6(M&BG& 0ؽ_>˝.U;yqoqAx1j}HWB}A?1Gxoxi(%wWՃdf,qZ]! 6N~WyzA1LjE]j8M\[W!4e/;!~D&iQIp!pd2 wNۣDHӾ>/#StF݀^\8@bB` ?jP)? YZjWӈ7@]մ:o.Cdi5ߩK.MF! Z턊q4:a\?[[4vbeh3C?:~v +055!`\ݯ ؎)!&v[Ѝu;q{;hz,S? Vpd!R5$p!\$wvۨg jGcdqV°ˠotKƽuUf|E]G5'˰{R_|>8̿YE'n%oM-1 mdM5_IiIJU,*8ygLApbK+ $ 0h!T $LK7u~͑ފ]lnJ66\3ot \#x[qb0YE=:gE%ҟO%2vսom Ο X";E JrL6z1brծ1Rj-Eyffɼ"evr&9۱Be1\y~wtûv;v;:bws u' :A "$A[5㷸?g NB%)-6VvɥH@3[zG\B@={%m=nC|Cb;SތBiT|ܣQg24Srlxg|JYMx)؎EKZ3gM0g=+ .}Z`.m^yHͤob0lvr vsIصra'}r@-!PK&o,u&1 7 wc4^b!*t;$IF<=f|7_)#X@?aGʍt[S 9iU1ܐ_DzM~H@ Lma:1Mf9 /מ^ںaAA }U]xg{8X4=ʖ[dFE$"jzH_ߐ1?wWBEnʌ]~Y2w~ -lfceXss}TK ;?WrIjpFq0|?>32JLVu V?U?wQq6-Fr*W>\ꉂ|#E5xY.T L=I -Ap{Ѽ-$6aG<_D(%CϟqbAx:U.Q  guC[v7r^q~:R.% I#sٕ2̀^f Jܐ]e0+'綩m^ (BHe϶wGO}㦆ʟߛwtY8p=}^tfHi?\[8 ~B "8"&&M2(PM.8hա](}ߟ|@!b~jy ,١QndU%,X!J^!A{<QЩgV02O _ ߏbOìO٥oϧ0:{u=@+øZ_hgk߂1DI߈ OJw ґ$a_+G קWq H6􈾎0E;O>|'K$ o'sJZu8csQ ZG/[P^PFbi![CHnLd=̽͹LfJ?@6~eyƻ%𰄶//3dv'QWR&fyQBd'vDo<0]B!/ڟN,"@YsKUb, ˯(&ӴJ?vwbg+u~t:R|+ZQ5" n$>u葟HΰvFV}oC7]eh5CEێ'/K hTJ͇Q돿 q}t_CO[+_9t0sq|dGMp[dz[Q~m0eBX[@1(m}Fe}!~՗ ga/o7̛,g;Wnu\Uh+w:ϊionf|qwZ C'u2lj!Ѹ$F4dX|kɁB_+с1NU0:6S-msԼ4D@bDЃ3+GD|TxcZF#?vY@:&ԡM6u{0mRГ(nfkO}n(^:>|n`_z,irQ(H7ew>5n)w05Q3k%2}nV(Ff?PAϢwcKrκM8BWȴ1SjXHtEZ@[NL\3C6QϵxڶȟjX+\%v(@Oo$/Sa <^u &ȇ&}#?"]M41m4_У{c!i#=<ٯ4 MϮ8<Y/Hg|TV@ob-׸l`H6=;I1k ?qF*̕$0picGow:Drص!!C}P3~{ANAmY_KqCN 6Рh# &Qp GR:YQȿ+e]H$>m i궇찂 Sf[f%{쐺anªHV/ INaQg@!$yu[;x8ZY@yjP}h+[5+=Sc%q|yC'ts<Ʉ=J'辱A}]_gf:iR}X$y<;cHVِFG@ ~vW#fbm @: Ju23  ^~ t W@!!4cY>՟.Y4&Zju4a*£Q37wU[fce@߭-]-@}=UQZ-O\[I4e{3$Q\,p\N?¹˳~U_aI3F--|Զ}T͢%f}07NKl"%X4&1 |]Y(tHYsr6ˎC8_ImvvZjZ"&9C" I?vP[#f]}E_