Oops
[deliverable/binutils-gdb.git] / gdb / hppa-linux-tdep.c
CommitLineData
9cbc6ef0 1/* Target-dependent code for GNU/Linux running on PA-RISC, for GDB.
50306a9d 2
197e01b6 3 Copyright (C) 2004 Free Software Foundation, Inc.
50306a9d
RC
4
5This file is part of GDB.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
197e01b6
EZ
19Foundation, Inc., 51 Franklin Street, Fifth Floor,
20Boston, MA 02110-1301, USA. */
50306a9d
RC
21
22#include "defs.h"
23#include "gdbcore.h"
24#include "osabi.h"
25#include "target.h"
26#include "objfiles.h"
27#include "solib-svr4.h"
28#include "glibc-tdep.h"
29#include "frame-unwind.h"
30#include "trad-frame.h"
31#include "dwarf2-frame.h"
d49771ef 32#include "value.h"
50306a9d
RC
33#include "hppa-tdep.h"
34
d49771ef
RC
35#include "elf/common.h"
36
50306a9d
RC
37#if 0
38/* Convert DWARF register number REG to the appropriate register
39 number used by GDB. */
40static int
41hppa_dwarf_reg_to_regnum (int reg)
42{
43 /* registers 0 - 31 are the same in both sets */
44 if (reg < 32)
45 return reg;
46
47 /* dwarf regs 32 to 85 are fpregs 4 - 31 */
48 if (reg >= 32 && reg <= 85)
34f75cc1 49 return HPPA_FP4_REGNUM + (reg - 32);
50306a9d 50
8a3fe4f8 51 warning (_("Unmapped DWARF Register #%d encountered."), reg);
50306a9d
RC
52 return -1;
53}
54#endif
55
56static void
57hppa_linux_target_write_pc (CORE_ADDR v, ptid_t ptid)
58{
59 /* Probably this should be done by the kernel, but it isn't. */
34f75cc1
RC
60 write_register_pid (HPPA_PCOQ_HEAD_REGNUM, v | 0x3, ptid);
61 write_register_pid (HPPA_PCOQ_TAIL_REGNUM, (v + 4) | 0x3, ptid);
50306a9d
RC
62}
63
64/* An instruction to match. */
65struct insn_pattern
66{
67 unsigned int data; /* See if it matches this.... */
68 unsigned int mask; /* ... with this mask. */
69};
70
71/* See bfd/elf32-hppa.c */
72static struct insn_pattern hppa_long_branch_stub[] = {
73 /* ldil LR'xxx,%r1 */
74 { 0x20200000, 0xffe00000 },
75 /* be,n RR'xxx(%sr4,%r1) */
76 { 0xe0202002, 0xffe02002 },
77 { 0, 0 }
78};
79
80static struct insn_pattern hppa_long_branch_pic_stub[] = {
81 /* b,l .+8, %r1 */
82 { 0xe8200000, 0xffe00000 },
83 /* addil LR'xxx - ($PIC_pcrel$0 - 4), %r1 */
84 { 0x28200000, 0xffe00000 },
85 /* be,n RR'xxxx - ($PIC_pcrel$0 - 8)(%sr4, %r1) */
86 { 0xe0202002, 0xffe02002 },
87 { 0, 0 }
88};
89
90static struct insn_pattern hppa_import_stub[] = {
91 /* addil LR'xxx, %dp */
92 { 0x2b600000, 0xffe00000 },
93 /* ldw RR'xxx(%r1), %r21 */
94 { 0x48350000, 0xffffb000 },
95 /* bv %r0(%r21) */
96 { 0xeaa0c000, 0xffffffff },
97 /* ldw RR'xxx+4(%r1), %r19 */
98 { 0x48330000, 0xffffb000 },
99 { 0, 0 }
100};
101
102static struct insn_pattern hppa_import_pic_stub[] = {
103 /* addil LR'xxx,%r19 */
104 { 0x2a600000, 0xffe00000 },
105 /* ldw RR'xxx(%r1),%r21 */
106 { 0x48350000, 0xffffb000 },
107 /* bv %r0(%r21) */
108 { 0xeaa0c000, 0xffffffff },
109 /* ldw RR'xxx+4(%r1),%r19 */
110 { 0x48330000, 0xffffb000 },
111 { 0, 0 },
112};
113
114static struct insn_pattern hppa_plt_stub[] = {
115 /* b,l 1b, %r20 - 1b is 3 insns before here */
116 { 0xea9f1fdd, 0xffffffff },
117 /* depi 0,31,2,%r20 */
118 { 0xd6801c1e, 0xffffffff },
119 { 0, 0 }
120};
121
122static struct insn_pattern hppa_sigtramp[] = {
123 /* ldi 0, %r25 or ldi 1, %r25 */
124 { 0x34190000, 0xfffffffd },
125 /* ldi __NR_rt_sigreturn, %r20 */
126 { 0x3414015a, 0xffffffff },
127 /* be,l 0x100(%sr2, %r0), %sr0, %r31 */
128 { 0xe4008200, 0xffffffff },
129 /* nop */
130 { 0x08000240, 0xffffffff },
131 { 0, 0 }
132};
133
134#define HPPA_MAX_INSN_PATTERN_LEN (4)
135
136/* Return non-zero if the instructions at PC match the series
137 described in PATTERN, or zero otherwise. PATTERN is an array of
138 'struct insn_pattern' objects, terminated by an entry whose mask is
139 zero.
140
141 When the match is successful, fill INSN[i] with what PATTERN[i]
142 matched. */
143static int
144insns_match_pattern (CORE_ADDR pc,
145 struct insn_pattern *pattern,
146 unsigned int *insn)
147{
148 int i;
149 CORE_ADDR npc = pc;
150
151 for (i = 0; pattern[i].mask; i++)
152 {
f4ca1d1f
RC
153 char buf[4];
154
1f602b35 155 deprecated_read_memory_nobpt (npc, buf, 4);
f4ca1d1f 156 insn[i] = extract_unsigned_integer (buf, 4);
50306a9d
RC
157 if ((insn[i] & pattern[i].mask) == pattern[i].data)
158 npc += 4;
159 else
160 return 0;
161 }
162 return 1;
163}
164
b546247c
RC
165/* The relaxed version of the insn matcher allows us to match from somewhere
166 inside the pattern, by looking backwards in the instruction scheme. */
167static int
168insns_match_pattern_relaxed (CORE_ADDR pc,
169 struct insn_pattern *pattern,
170 unsigned int *insn)
171{
172 int pat_len = 0;
173 int offset;
174
175 while (pattern[pat_len].mask)
176 pat_len++;
177
178 for (offset = 0; offset < pat_len; offset++)
179 {
180 if (insns_match_pattern (pc - offset * 4,
181 pattern, insn))
182 return 1;
183 }
184
185 return 0;
186}
187
50306a9d
RC
188static int
189hppa_linux_in_dyncall (CORE_ADDR pc)
190{
b546247c
RC
191 struct unwind_table_entry *u;
192 u = find_unwind_entry (hppa_symbol_address ("$$dyncall"));
193
194 if (!u)
195 return 0;
196
197 return pc >= u->region_start && pc <= u->region_end;
50306a9d
RC
198}
199
200/* There are several kinds of "trampolines" that we need to deal with:
201 - long branch stubs: these are inserted by the linker when a branch
202 target is too far away for a branch insn to reach
203 - plt stubs: these should go into the .plt section, so are easy to find
204 - import stubs: used to call from object to shared lib or shared lib to
205 shared lib; these go in regular text sections. In fact the linker tries
206 to put them throughout the code because branches have limited reachability.
207 We use the same mechanism as ppc64 to recognize the stub insn patterns.
208 - $$dyncall: similar to hpux, hppa-linux uses $$dyncall for indirect function
209 calls. $$dyncall is exported by libgcc.a */
210static int
211hppa_linux_in_solib_call_trampoline (CORE_ADDR pc, char *name)
212{
213 unsigned int insn[HPPA_MAX_INSN_PATTERN_LEN];
214 int r;
b546247c
RC
215 struct unwind_table_entry *u;
216
217 /* on hppa-linux, linker stubs have no unwind information. Since the pattern
218 matching for linker stubs can be quite slow, we try to avoid it if
219 we can. */
220 u = find_unwind_entry (pc);
50306a9d
RC
221
222 r = in_plt_section (pc, name)
223 || hppa_linux_in_dyncall (pc)
b546247c
RC
224 || (u == NULL
225 && (insns_match_pattern_relaxed (pc, hppa_import_stub, insn)
226 || insns_match_pattern_relaxed (pc, hppa_import_pic_stub, insn)
227 || insns_match_pattern_relaxed (pc, hppa_long_branch_stub, insn)
228 || insns_match_pattern_relaxed (pc, hppa_long_branch_pic_stub, insn)));
50306a9d
RC
229
230 return r;
231}
232
233static CORE_ADDR
234hppa_linux_skip_trampoline_code (CORE_ADDR pc)
235{
236 unsigned int insn[HPPA_MAX_INSN_PATTERN_LEN];
237 int dp_rel, pic_rel;
238
239 /* dyncall handles both PLABELs and direct addresses */
240 if (hppa_linux_in_dyncall (pc))
241 {
242 pc = (CORE_ADDR) read_register (22);
243
244 /* PLABELs have bit 30 set; if it's a PLABEL, then dereference it */
245 if (pc & 0x2)
246 pc = (CORE_ADDR) read_memory_integer (pc & ~0x3, TARGET_PTR_BIT / 8);
247
248 return pc;
249 }
250
251 dp_rel = pic_rel = 0;
252 if ((dp_rel = insns_match_pattern (pc, hppa_import_stub, insn))
253 || (pic_rel = insns_match_pattern (pc, hppa_import_pic_stub, insn)))
254 {
255 /* Extract the target address from the addil/ldw sequence. */
256 pc = hppa_extract_21 (insn[0]) + hppa_extract_14 (insn[1]);
257
258 if (dp_rel)
259 pc += (CORE_ADDR) read_register (27);
260 else
261 pc += (CORE_ADDR) read_register (19);
262
263 /* fallthrough */
264 }
265
266 if (in_plt_section (pc, NULL))
267 {
268 pc = (CORE_ADDR) read_memory_integer (pc, TARGET_PTR_BIT / 8);
269
270 /* if the plt slot has not yet been resolved, the target will
271 be the plt stub */
272 if (in_plt_section (pc, NULL))
273 {
274 /* Sanity check: are we pointing to the plt stub? */
275 if (insns_match_pattern (pc, hppa_plt_stub, insn))
276 {
277 /* this should point to the fixup routine */
278 pc = (CORE_ADDR) read_memory_integer (pc + 8, TARGET_PTR_BIT / 8);
279 }
280 else
281 {
8a3fe4f8 282 error (_("Cannot resolve plt stub at 0x%s."),
50306a9d
RC
283 paddr_nz (pc));
284 pc = 0;
285 }
286 }
287 }
288
289 return pc;
290}
291
292/* Signal frames. */
293
294/* (This is derived from MD_FALLBACK_FRAME_STATE_FOR in gcc.)
295
296 Unfortunately, because of various bugs and changes to the kernel,
297 we have several cases to deal with.
298
299 In 2.4, the signal trampoline is 4 bytes, and pc should point directly at
300 the beginning of the trampoline and struct rt_sigframe.
301
302 In <= 2.6.5-rc2-pa3, the signal trampoline is 9 bytes, and pc points at
303 the 4th word in the trampoline structure. This is wrong, it should point
304 at the 5th word. This is fixed in 2.6.5-rc2-pa4.
305
306 To detect these cases, we first take pc, align it to 64-bytes
307 to get the beginning of the signal frame, and then check offsets 0, 4
308 and 5 to see if we found the beginning of the trampoline. This will
309 tell us how to locate the sigcontext structure.
310
311 Note that with a 2.4 64-bit kernel, the signal context is not properly
312 passed back to userspace so the unwind will not work correctly. */
313static CORE_ADDR
2f0e8c7a 314hppa_linux_sigtramp_find_sigcontext (CORE_ADDR pc)
50306a9d
RC
315{
316 unsigned int dummy[HPPA_MAX_INSN_PATTERN_LEN];
317 int offs = 0;
318 int try;
319 /* offsets to try to find the trampoline */
320 static int pcoffs[] = { 0, 4*4, 5*4 };
321 /* offsets to the rt_sigframe structure */
322 static int sfoffs[] = { 4*4, 10*4, 10*4 };
2f0e8c7a
RC
323 CORE_ADDR sp;
324
325 /* Most of the time, this will be correct. The one case when this will
326 fail is if the user defined an alternate stack, in which case the
327 beginning of the stack will not be align_down (pc, 64). */
328 sp = align_down (pc, 64);
50306a9d
RC
329
330 /* rt_sigreturn trampoline:
331 3419000x ldi 0, %r25 or ldi 1, %r25 (x = 0 or 2)
332 3414015a ldi __NR_rt_sigreturn, %r20
333 e4008200 be,l 0x100(%sr2, %r0), %sr0, %r31
334 08000240 nop */
335
336 for (try = 0; try < ARRAY_SIZE (pcoffs); try++)
337 {
338 if (insns_match_pattern (sp + pcoffs[try], hppa_sigtramp, dummy))
339 {
340 offs = sfoffs[try];
341 break;
342 }
343 }
344
345 if (offs == 0)
2f0e8c7a
RC
346 {
347 if (insns_match_pattern (pc, hppa_sigtramp, dummy))
348 {
349 /* sigaltstack case: we have no way of knowing which offset to
350 use in this case; default to new kernel handling. If this is
351 wrong the unwinding will fail. */
352 try = 2;
353 sp = pc - pcoffs[try];
354 }
355 else
356 {
357 return 0;
358 }
359 }
50306a9d
RC
360
361 /* sp + sfoffs[try] points to a struct rt_sigframe, which contains
362 a struct siginfo and a struct ucontext. struct ucontext contains
363 a struct sigcontext. Return an offset to this sigcontext here. Too
364 bad we cannot include system specific headers :-(.
365 sizeof(struct siginfo) == 128
366 offsetof(struct ucontext, uc_mcontext) == 24. */
367 return sp + sfoffs[try] + 128 + 24;
368}
369
370struct hppa_linux_sigtramp_unwind_cache
371{
372 CORE_ADDR base;
373 struct trad_frame_saved_reg *saved_regs;
374};
375
376static struct hppa_linux_sigtramp_unwind_cache *
377hppa_linux_sigtramp_frame_unwind_cache (struct frame_info *next_frame,
378 void **this_cache)
379{
380 struct gdbarch *gdbarch = get_frame_arch (next_frame);
381 struct hppa_linux_sigtramp_unwind_cache *info;
2f0e8c7a 382 CORE_ADDR pc, scptr;
50306a9d
RC
383 int i;
384
385 if (*this_cache)
386 return *this_cache;
387
388 info = FRAME_OBSTACK_ZALLOC (struct hppa_linux_sigtramp_unwind_cache);
389 *this_cache = info;
390 info->saved_regs = trad_frame_alloc_saved_regs (next_frame);
391
392 pc = frame_pc_unwind (next_frame);
2f0e8c7a 393 scptr = hppa_linux_sigtramp_find_sigcontext (pc);
50306a9d
RC
394
395 /* structure of struct sigcontext:
396
397 struct sigcontext {
398 unsigned long sc_flags;
399 unsigned long sc_gr[32];
400 unsigned long long sc_fr[32];
401 unsigned long sc_iasq[2];
402 unsigned long sc_iaoq[2];
403 unsigned long sc_sar; */
404
405 /* Skip sc_flags. */
406 scptr += 4;
407
408 /* GR[0] is the psw, we don't restore that. */
409 scptr += 4;
410
411 /* General registers. */
412 for (i = 1; i < 32; i++)
413 {
34f75cc1 414 info->saved_regs[HPPA_R0_REGNUM + i].addr = scptr;
50306a9d
RC
415 scptr += 4;
416 }
417
418 /* Pad. */
419 scptr += 4;
420
421 /* FP regs; FP0-3 are not restored. */
422 scptr += (8 * 4);
423
424 for (i = 4; i < 32; i++)
425 {
426 info->saved_regs[HPPA_FP0_REGNUM + (i * 2)].addr = scptr;
427 scptr += 4;
428 info->saved_regs[HPPA_FP0_REGNUM + (i * 2) + 1].addr = scptr;
429 scptr += 4;
430 }
431
432 /* IASQ/IAOQ. */
34f75cc1 433 info->saved_regs[HPPA_PCSQ_HEAD_REGNUM].addr = scptr;
50306a9d 434 scptr += 4;
34f75cc1 435 info->saved_regs[HPPA_PCSQ_TAIL_REGNUM].addr = scptr;
50306a9d
RC
436 scptr += 4;
437
34f75cc1 438 info->saved_regs[HPPA_PCOQ_HEAD_REGNUM].addr = scptr;
50306a9d 439 scptr += 4;
34f75cc1 440 info->saved_regs[HPPA_PCOQ_TAIL_REGNUM].addr = scptr;
50306a9d
RC
441 scptr += 4;
442
2f0e8c7a 443 info->base = frame_unwind_register_unsigned (next_frame, HPPA_SP_REGNUM);
50306a9d
RC
444
445 return info;
446}
447
448static void
449hppa_linux_sigtramp_frame_this_id (struct frame_info *next_frame,
450 void **this_prologue_cache,
451 struct frame_id *this_id)
452{
453 struct hppa_linux_sigtramp_unwind_cache *info
454 = hppa_linux_sigtramp_frame_unwind_cache (next_frame, this_prologue_cache);
455 *this_id = frame_id_build (info->base, frame_pc_unwind (next_frame));
456}
457
458static void
459hppa_linux_sigtramp_frame_prev_register (struct frame_info *next_frame,
460 void **this_prologue_cache,
461 int regnum, int *optimizedp,
462 enum lval_type *lvalp,
463 CORE_ADDR *addrp,
0da28f8a 464 int *realnump, void *valuep)
50306a9d
RC
465{
466 struct hppa_linux_sigtramp_unwind_cache *info
467 = hppa_linux_sigtramp_frame_unwind_cache (next_frame, this_prologue_cache);
0da28f8a
RC
468 hppa_frame_prev_register_helper (next_frame, info->saved_regs, regnum,
469 optimizedp, lvalp, addrp, realnump, valuep);
50306a9d
RC
470}
471
472static const struct frame_unwind hppa_linux_sigtramp_frame_unwind = {
473 SIGTRAMP_FRAME,
474 hppa_linux_sigtramp_frame_this_id,
475 hppa_linux_sigtramp_frame_prev_register
476};
477
478/* hppa-linux always uses "new-style" rt-signals. The signal handler's return
479 address should point to a signal trampoline on the stack. The signal
480 trampoline is embedded in a rt_sigframe structure that is aligned on
481 the stack. We take advantage of the fact that sp must be 64-byte aligned,
482 and the trampoline is small, so by rounding down the trampoline address
483 we can find the beginning of the struct rt_sigframe. */
484static const struct frame_unwind *
485hppa_linux_sigtramp_unwind_sniffer (struct frame_info *next_frame)
486{
487 CORE_ADDR pc = frame_pc_unwind (next_frame);
50306a9d 488
2f0e8c7a 489 if (hppa_linux_sigtramp_find_sigcontext (pc))
50306a9d
RC
490 return &hppa_linux_sigtramp_frame_unwind;
491
492 return NULL;
493}
494
d49771ef
RC
495/* Attempt to find (and return) the global pointer for the given
496 function.
497
498 This is a rather nasty bit of code searchs for the .dynamic section
499 in the objfile corresponding to the pc of the function we're trying
500 to call. Once it finds the addresses at which the .dynamic section
501 lives in the child process, it scans the Elf32_Dyn entries for a
502 DT_PLTGOT tag. If it finds one of these, the corresponding
503 d_un.d_ptr value is the global pointer. */
504
505static CORE_ADDR
506hppa_linux_find_global_pointer (struct value *function)
507{
508 struct obj_section *faddr_sect;
509 CORE_ADDR faddr;
510
511 faddr = value_as_address (function);
512
513 /* Is this a plabel? If so, dereference it to get the gp value. */
514 if (faddr & 2)
515 {
516 int status;
517 char buf[4];
518
519 faddr &= ~3;
520
521 status = target_read_memory (faddr + 4, buf, sizeof (buf));
522 if (status == 0)
523 return extract_unsigned_integer (buf, sizeof (buf));
524 }
525
526 /* If the address is in the plt section, then the real function hasn't
527 yet been fixed up by the linker so we cannot determine the gp of
528 that function. */
529 if (in_plt_section (faddr, NULL))
530 return 0;
531
532 faddr_sect = find_pc_section (faddr);
533 if (faddr_sect != NULL)
534 {
535 struct obj_section *osect;
536
537 ALL_OBJFILE_OSECTIONS (faddr_sect->objfile, osect)
538 {
539 if (strcmp (osect->the_bfd_section->name, ".dynamic") == 0)
540 break;
541 }
542
543 if (osect < faddr_sect->objfile->sections_end)
544 {
545 CORE_ADDR addr;
546
547 addr = osect->addr;
548 while (addr < osect->endaddr)
549 {
550 int status;
551 LONGEST tag;
552 char buf[4];
553
554 status = target_read_memory (addr, buf, sizeof (buf));
555 if (status != 0)
556 break;
557 tag = extract_signed_integer (buf, sizeof (buf));
558
559 if (tag == DT_PLTGOT)
560 {
561 CORE_ADDR global_pointer;
562
563 status = target_read_memory (addr + 4, buf, sizeof (buf));
564 if (status != 0)
565 break;
566 global_pointer = extract_unsigned_integer (buf, sizeof (buf));
567
568 /* The payoff... */
569 return global_pointer;
570 }
571
572 if (tag == DT_NULL)
573 break;
574
575 addr += 8;
576 }
577 }
578 }
579 return 0;
580}
581
50306a9d
RC
582/* Forward declarations. */
583extern initialize_file_ftype _initialize_hppa_linux_tdep;
584
585static void
586hppa_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
587{
588 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
589
9cbc6ef0 590 /* GNU/Linux is always ELF. */
50306a9d
RC
591 tdep->is_elf = 1;
592
d49771ef
RC
593 tdep->find_global_pointer = hppa_linux_find_global_pointer;
594
50306a9d
RC
595 set_gdbarch_write_pc (gdbarch, hppa_linux_target_write_pc);
596
597 frame_unwind_append_sniffer (gdbarch, hppa_linux_sigtramp_unwind_sniffer);
598
599 /* GNU/Linux uses SVR4-style shared libraries. */
600 set_solib_svr4_fetch_link_map_offsets
601 (gdbarch, svr4_ilp32_fetch_link_map_offsets);
602
84674fe1 603 tdep->in_solib_call_trampoline = hppa_linux_in_solib_call_trampoline;
50306a9d
RC
604 set_gdbarch_skip_trampoline_code
605 (gdbarch, hppa_linux_skip_trampoline_code);
606
607 /* GNU/Linux uses the dynamic linker included in the GNU C Library. */
608 set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
609
3a7d1c27
RC
610 /* On hppa-linux, currently, sizeof(long double) == 8. There has been
611 some discussions to support 128-bit long double, but it requires some
612 more work in gcc and glibc first. */
613 set_gdbarch_long_double_bit (gdbarch, 64);
614
50306a9d
RC
615#if 0
616 /* Dwarf-2 unwinding support. Not yet working. */
617 set_gdbarch_dwarf_reg_to_regnum (gdbarch, hppa_dwarf_reg_to_regnum);
618 set_gdbarch_dwarf2_reg_to_regnum (gdbarch, hppa_dwarf_reg_to_regnum);
619 frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer);
620 frame_base_append_sniffer (gdbarch, dwarf2_frame_base_sniffer);
621#endif
b2756930
KB
622
623 /* Enable TLS support. */
624 set_gdbarch_fetch_tls_load_module_address (gdbarch,
625 svr4_fetch_objfile_link_map);
50306a9d
RC
626}
627
628void
629_initialize_hppa_linux_tdep (void)
630{
631 gdbarch_register_osabi (bfd_arch_hppa, 0, GDB_OSABI_LINUX, hppa_linux_init_abi);
632}
This page took 0.185815 seconds and 4 git commands to generate.