1*7304104dSAndroid Build Coastguard Worker /* Functions to handle creation of Linux archives.
2*7304104dSAndroid Build Coastguard Worker Copyright (C) 2007-2012, 2016 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker This file is part of elfutils.
4*7304104dSAndroid Build Coastguard Worker Written by Ulrich Drepper <[email protected]>, 2007.
5*7304104dSAndroid Build Coastguard Worker
6*7304104dSAndroid Build Coastguard Worker This file is free software; you can redistribute it and/or modify
7*7304104dSAndroid Build Coastguard Worker it under the terms of the GNU General Public License as published by
8*7304104dSAndroid Build Coastguard Worker the Free Software Foundation; either version 3 of the License, or
9*7304104dSAndroid Build Coastguard Worker (at your option) any later version.
10*7304104dSAndroid Build Coastguard Worker
11*7304104dSAndroid Build Coastguard Worker elfutils is distributed in the hope that it will be useful, but
12*7304104dSAndroid Build Coastguard Worker WITHOUT ANY WARRANTY; without even the implied warranty of
13*7304104dSAndroid Build Coastguard Worker MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14*7304104dSAndroid Build Coastguard Worker GNU General Public License for more details.
15*7304104dSAndroid Build Coastguard Worker
16*7304104dSAndroid Build Coastguard Worker You should have received a copy of the GNU General Public License
17*7304104dSAndroid Build Coastguard Worker along with this program. If not, see <http://www.gnu.org/licenses/>. */
18*7304104dSAndroid Build Coastguard Worker
19*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
20*7304104dSAndroid Build Coastguard Worker # include <config.h>
21*7304104dSAndroid Build Coastguard Worker #endif
22*7304104dSAndroid Build Coastguard Worker
23*7304104dSAndroid Build Coastguard Worker #include <assert.h>
24*7304104dSAndroid Build Coastguard Worker #include <gelf.h>
25*7304104dSAndroid Build Coastguard Worker #include <inttypes.h>
26*7304104dSAndroid Build Coastguard Worker #include <stdio.h>
27*7304104dSAndroid Build Coastguard Worker #include <stdlib.h>
28*7304104dSAndroid Build Coastguard Worker #include <time.h>
29*7304104dSAndroid Build Coastguard Worker
30*7304104dSAndroid Build Coastguard Worker #include <libeu.h>
31*7304104dSAndroid Build Coastguard Worker
32*7304104dSAndroid Build Coastguard Worker #include "system.h"
33*7304104dSAndroid Build Coastguard Worker #include "arlib.h"
34*7304104dSAndroid Build Coastguard Worker
35*7304104dSAndroid Build Coastguard Worker
36*7304104dSAndroid Build Coastguard Worker /* The one symbol table we hanble. */
37*7304104dSAndroid Build Coastguard Worker struct arlib_symtab symtab;
38*7304104dSAndroid Build Coastguard Worker
39*7304104dSAndroid Build Coastguard Worker
40*7304104dSAndroid Build Coastguard Worker /* Initialize ARLIB_SYMTAB structure. */
41*7304104dSAndroid Build Coastguard Worker void
arlib_init(void)42*7304104dSAndroid Build Coastguard Worker arlib_init (void)
43*7304104dSAndroid Build Coastguard Worker {
44*7304104dSAndroid Build Coastguard Worker #define obstack_chunk_alloc xmalloc
45*7304104dSAndroid Build Coastguard Worker #define obstack_chunk_free free
46*7304104dSAndroid Build Coastguard Worker obstack_init (&symtab.symsoffob);
47*7304104dSAndroid Build Coastguard Worker obstack_init (&symtab.symsnameob);
48*7304104dSAndroid Build Coastguard Worker obstack_init (&symtab.longnamesob);
49*7304104dSAndroid Build Coastguard Worker
50*7304104dSAndroid Build Coastguard Worker /* We add the archive header here as well, that avoids allocating
51*7304104dSAndroid Build Coastguard Worker another memory block. */
52*7304104dSAndroid Build Coastguard Worker struct ar_hdr ar_hdr;
53*7304104dSAndroid Build Coastguard Worker memcpy (ar_hdr.ar_name, "/ ", sizeof (ar_hdr.ar_name));
54*7304104dSAndroid Build Coastguard Worker /* Using snprintf here has a problem: the call always wants to add a
55*7304104dSAndroid Build Coastguard Worker NUL byte. We could use a trick whereby we specify the target
56*7304104dSAndroid Build Coastguard Worker buffer size longer than it is and this would not actually fail,
57*7304104dSAndroid Build Coastguard Worker since all the fields are consecutive and we fill them in
58*7304104dSAndroid Build Coastguard Worker sequence (i.e., the NUL byte gets overwritten). But
59*7304104dSAndroid Build Coastguard Worker _FORTIFY_SOURCE=2 would not let us play these games. Therefore
60*7304104dSAndroid Build Coastguard Worker we play it safe. */
61*7304104dSAndroid Build Coastguard Worker char tmpbuf[sizeof (ar_hdr.ar_date) + 1];
62*7304104dSAndroid Build Coastguard Worker int s = snprintf (tmpbuf, sizeof (tmpbuf), "%-*lld",
63*7304104dSAndroid Build Coastguard Worker (int) sizeof (ar_hdr.ar_date),
64*7304104dSAndroid Build Coastguard Worker (arlib_deterministic_output ? 0
65*7304104dSAndroid Build Coastguard Worker : (long long int) time (NULL)));
66*7304104dSAndroid Build Coastguard Worker memcpy (ar_hdr.ar_date, tmpbuf, s);
67*7304104dSAndroid Build Coastguard Worker assert ((sizeof (struct ar_hdr) % sizeof (uint32_t)) == 0);
68*7304104dSAndroid Build Coastguard Worker
69*7304104dSAndroid Build Coastguard Worker /* Note the string for the ar_uid and ar_gid cases is longer than
70*7304104dSAndroid Build Coastguard Worker necessary. This does not matter since we copy only as much as
71*7304104dSAndroid Build Coastguard Worker necessary but it helps the compiler to use the same string for
72*7304104dSAndroid Build Coastguard Worker the ar_mode case. */
73*7304104dSAndroid Build Coastguard Worker memcpy (ar_hdr.ar_uid, "0 ", sizeof (ar_hdr.ar_uid));
74*7304104dSAndroid Build Coastguard Worker memcpy (ar_hdr.ar_gid, "0 ", sizeof (ar_hdr.ar_gid));
75*7304104dSAndroid Build Coastguard Worker memcpy (ar_hdr.ar_mode, "0 ", sizeof (ar_hdr.ar_mode));
76*7304104dSAndroid Build Coastguard Worker memcpy (ar_hdr.ar_fmag, ARFMAG, sizeof (ar_hdr.ar_fmag));
77*7304104dSAndroid Build Coastguard Worker
78*7304104dSAndroid Build Coastguard Worker /* Add the archive header to the file content. */
79*7304104dSAndroid Build Coastguard Worker obstack_grow (&symtab.symsoffob, &ar_hdr, sizeof (ar_hdr));
80*7304104dSAndroid Build Coastguard Worker
81*7304104dSAndroid Build Coastguard Worker /* The first word in the offset table specifies the size. Create
82*7304104dSAndroid Build Coastguard Worker such an entry now. The real value will be filled-in later. For
83*7304104dSAndroid Build Coastguard Worker all supported platforms the following is true. */
84*7304104dSAndroid Build Coastguard Worker assert (sizeof (uint32_t) == sizeof (int));
85*7304104dSAndroid Build Coastguard Worker obstack_int_grow (&symtab.symsoffob, 0);
86*7304104dSAndroid Build Coastguard Worker
87*7304104dSAndroid Build Coastguard Worker /* The long name obstack also gets its archive header. As above,
88*7304104dSAndroid Build Coastguard Worker some of the input strings are longer than required but we only
89*7304104dSAndroid Build Coastguard Worker copy the necessary part. */
90*7304104dSAndroid Build Coastguard Worker memcpy (ar_hdr.ar_name, "// ", sizeof (ar_hdr.ar_name));
91*7304104dSAndroid Build Coastguard Worker memcpy (ar_hdr.ar_date, " ", sizeof (ar_hdr.ar_date));
92*7304104dSAndroid Build Coastguard Worker memcpy (ar_hdr.ar_uid, " ", sizeof (ar_hdr.ar_uid));
93*7304104dSAndroid Build Coastguard Worker memcpy (ar_hdr.ar_gid, " ", sizeof (ar_hdr.ar_gid));
94*7304104dSAndroid Build Coastguard Worker memcpy (ar_hdr.ar_mode, " ", sizeof (ar_hdr.ar_mode));
95*7304104dSAndroid Build Coastguard Worker /* The ar_size field will be filled in later and ar_fmag is already OK. */
96*7304104dSAndroid Build Coastguard Worker obstack_grow (&symtab.longnamesob, &ar_hdr, sizeof (ar_hdr));
97*7304104dSAndroid Build Coastguard Worker
98*7304104dSAndroid Build Coastguard Worker /* All other members are zero. */
99*7304104dSAndroid Build Coastguard Worker symtab.symsofflen = 0;
100*7304104dSAndroid Build Coastguard Worker symtab.symsoff = NULL;
101*7304104dSAndroid Build Coastguard Worker symtab.symsnamelen = 0;
102*7304104dSAndroid Build Coastguard Worker symtab.symsname = NULL;
103*7304104dSAndroid Build Coastguard Worker }
104*7304104dSAndroid Build Coastguard Worker
105*7304104dSAndroid Build Coastguard Worker
106*7304104dSAndroid Build Coastguard Worker /* Finalize ARLIB_SYMTAB content. */
107*7304104dSAndroid Build Coastguard Worker void
arlib_finalize(void)108*7304104dSAndroid Build Coastguard Worker arlib_finalize (void)
109*7304104dSAndroid Build Coastguard Worker {
110*7304104dSAndroid Build Coastguard Worker /* Note that the size is stored as decimal string in 10 chars,
111*7304104dSAndroid Build Coastguard Worker without zero terminator (we add + 1 here only so snprintf can
112*7304104dSAndroid Build Coastguard Worker put it at the end, we then don't use it when we memcpy it). */
113*7304104dSAndroid Build Coastguard Worker char tmpbuf[sizeof (((struct ar_hdr *) NULL)->ar_size) + 1];
114*7304104dSAndroid Build Coastguard Worker
115*7304104dSAndroid Build Coastguard Worker symtab.longnameslen = obstack_object_size (&symtab.longnamesob);
116*7304104dSAndroid Build Coastguard Worker if (symtab.longnameslen != sizeof (struct ar_hdr))
117*7304104dSAndroid Build Coastguard Worker {
118*7304104dSAndroid Build Coastguard Worker if ((symtab.longnameslen & 1) != 0)
119*7304104dSAndroid Build Coastguard Worker {
120*7304104dSAndroid Build Coastguard Worker /* Add one more byte to make length even. */
121*7304104dSAndroid Build Coastguard Worker obstack_grow (&symtab.longnamesob, "\n", 1);
122*7304104dSAndroid Build Coastguard Worker ++symtab.longnameslen;
123*7304104dSAndroid Build Coastguard Worker }
124*7304104dSAndroid Build Coastguard Worker
125*7304104dSAndroid Build Coastguard Worker symtab.longnames = obstack_finish (&symtab.longnamesob);
126*7304104dSAndroid Build Coastguard Worker
127*7304104dSAndroid Build Coastguard Worker int s = snprintf (tmpbuf, sizeof (tmpbuf), "%-*" PRIu32 "",
128*7304104dSAndroid Build Coastguard Worker (int) sizeof (((struct ar_hdr *) NULL)->ar_size),
129*7304104dSAndroid Build Coastguard Worker (uint32_t) (symtab.longnameslen - sizeof (struct ar_hdr)));
130*7304104dSAndroid Build Coastguard Worker memcpy (&((struct ar_hdr *) symtab.longnames)->ar_size, tmpbuf, s);
131*7304104dSAndroid Build Coastguard Worker }
132*7304104dSAndroid Build Coastguard Worker
133*7304104dSAndroid Build Coastguard Worker symtab.symsofflen = obstack_object_size (&symtab.symsoffob);
134*7304104dSAndroid Build Coastguard Worker assert (symtab.symsofflen % sizeof (uint32_t) == 0);
135*7304104dSAndroid Build Coastguard Worker if (symtab.symsofflen != 0)
136*7304104dSAndroid Build Coastguard Worker {
137*7304104dSAndroid Build Coastguard Worker symtab.symsoff = (uint32_t *) obstack_finish (&symtab.symsoffob);
138*7304104dSAndroid Build Coastguard Worker
139*7304104dSAndroid Build Coastguard Worker /* Fill in the number of offsets now. */
140*7304104dSAndroid Build Coastguard Worker symtab.symsoff[AR_HDR_WORDS] = le_bswap_32 ((symtab.symsofflen
141*7304104dSAndroid Build Coastguard Worker - sizeof (struct ar_hdr))
142*7304104dSAndroid Build Coastguard Worker / sizeof (uint32_t) - 1);
143*7304104dSAndroid Build Coastguard Worker }
144*7304104dSAndroid Build Coastguard Worker
145*7304104dSAndroid Build Coastguard Worker symtab.symsnamelen = obstack_object_size (&symtab.symsnameob);
146*7304104dSAndroid Build Coastguard Worker if ((symtab.symsnamelen & 1) != 0)
147*7304104dSAndroid Build Coastguard Worker {
148*7304104dSAndroid Build Coastguard Worker /* Add one more NUL byte to make length even. */
149*7304104dSAndroid Build Coastguard Worker obstack_grow (&symtab.symsnameob, "", 1);
150*7304104dSAndroid Build Coastguard Worker ++symtab.symsnamelen;
151*7304104dSAndroid Build Coastguard Worker }
152*7304104dSAndroid Build Coastguard Worker symtab.symsname = obstack_finish (&symtab.symsnameob);
153*7304104dSAndroid Build Coastguard Worker
154*7304104dSAndroid Build Coastguard Worker /* Determine correction for the offsets in the symbol table. */
155*7304104dSAndroid Build Coastguard Worker off_t disp = 0;
156*7304104dSAndroid Build Coastguard Worker if (symtab.symsnamelen > 0)
157*7304104dSAndroid Build Coastguard Worker disp = symtab.symsofflen + symtab.symsnamelen;
158*7304104dSAndroid Build Coastguard Worker if (symtab.longnameslen > sizeof (struct ar_hdr))
159*7304104dSAndroid Build Coastguard Worker disp += symtab.longnameslen;
160*7304104dSAndroid Build Coastguard Worker
161*7304104dSAndroid Build Coastguard Worker if (disp != 0 && symtab.symsoff != NULL)
162*7304104dSAndroid Build Coastguard Worker {
163*7304104dSAndroid Build Coastguard Worker uint32_t nsyms = le_bswap_32 (symtab.symsoff[AR_HDR_WORDS]);
164*7304104dSAndroid Build Coastguard Worker
165*7304104dSAndroid Build Coastguard Worker for (uint32_t cnt = 1; cnt <= nsyms; ++cnt)
166*7304104dSAndroid Build Coastguard Worker {
167*7304104dSAndroid Build Coastguard Worker uint32_t val = le_bswap_32 (symtab.symsoff[AR_HDR_WORDS + cnt]);
168*7304104dSAndroid Build Coastguard Worker val += disp;
169*7304104dSAndroid Build Coastguard Worker symtab.symsoff[AR_HDR_WORDS + cnt] = le_bswap_32 (val);
170*7304104dSAndroid Build Coastguard Worker }
171*7304104dSAndroid Build Coastguard Worker }
172*7304104dSAndroid Build Coastguard Worker
173*7304104dSAndroid Build Coastguard Worker /* See comment for ar_date above. */
174*7304104dSAndroid Build Coastguard Worker memcpy (&((struct ar_hdr *) symtab.symsoff)->ar_size, tmpbuf,
175*7304104dSAndroid Build Coastguard Worker snprintf (tmpbuf, sizeof (tmpbuf), "%-*" PRIu32 "",
176*7304104dSAndroid Build Coastguard Worker (int) sizeof (((struct ar_hdr *) NULL)->ar_size),
177*7304104dSAndroid Build Coastguard Worker (uint32_t) (symtab.symsofflen + symtab.symsnamelen
178*7304104dSAndroid Build Coastguard Worker - sizeof (struct ar_hdr))));
179*7304104dSAndroid Build Coastguard Worker }
180*7304104dSAndroid Build Coastguard Worker
181*7304104dSAndroid Build Coastguard Worker
182*7304104dSAndroid Build Coastguard Worker /* Free resources for ARLIB_SYMTAB. */
183*7304104dSAndroid Build Coastguard Worker void
arlib_fini(void)184*7304104dSAndroid Build Coastguard Worker arlib_fini (void)
185*7304104dSAndroid Build Coastguard Worker {
186*7304104dSAndroid Build Coastguard Worker obstack_free (&symtab.symsoffob, NULL);
187*7304104dSAndroid Build Coastguard Worker obstack_free (&symtab.symsnameob, NULL);
188*7304104dSAndroid Build Coastguard Worker obstack_free (&symtab.longnamesob, NULL);
189*7304104dSAndroid Build Coastguard Worker }
190*7304104dSAndroid Build Coastguard Worker
191*7304104dSAndroid Build Coastguard Worker
192*7304104dSAndroid Build Coastguard Worker /* Add name a file offset of a symbol. */
193*7304104dSAndroid Build Coastguard Worker void
arlib_add_symref(const char * symname,off_t symoff)194*7304104dSAndroid Build Coastguard Worker arlib_add_symref (const char *symname, off_t symoff)
195*7304104dSAndroid Build Coastguard Worker {
196*7304104dSAndroid Build Coastguard Worker /* For all supported platforms the following is true. */
197*7304104dSAndroid Build Coastguard Worker assert (sizeof (uint32_t) == sizeof (int));
198*7304104dSAndroid Build Coastguard Worker obstack_int_grow (&symtab.symsoffob, (int) le_bswap_32 (symoff));
199*7304104dSAndroid Build Coastguard Worker
200*7304104dSAndroid Build Coastguard Worker size_t symname_len = strlen (symname) + 1;
201*7304104dSAndroid Build Coastguard Worker obstack_grow (&symtab.symsnameob, symname, symname_len);
202*7304104dSAndroid Build Coastguard Worker }
203*7304104dSAndroid Build Coastguard Worker
204*7304104dSAndroid Build Coastguard Worker
205*7304104dSAndroid Build Coastguard Worker /* Add symbols from ELF with value OFFSET to the symbol table SYMTAB. */
206*7304104dSAndroid Build Coastguard Worker void
arlib_add_symbols(Elf * elf,const char * arfname,const char * membername,off_t off)207*7304104dSAndroid Build Coastguard Worker arlib_add_symbols (Elf *elf, const char *arfname, const char *membername,
208*7304104dSAndroid Build Coastguard Worker off_t off)
209*7304104dSAndroid Build Coastguard Worker {
210*7304104dSAndroid Build Coastguard Worker if (sizeof (off) > sizeof (uint32_t) && off > ~((uint32_t) 0))
211*7304104dSAndroid Build Coastguard Worker /* The archive is too big. */
212*7304104dSAndroid Build Coastguard Worker error_exit (0, _("the archive '%s' is too large"),
213*7304104dSAndroid Build Coastguard Worker arfname);
214*7304104dSAndroid Build Coastguard Worker
215*7304104dSAndroid Build Coastguard Worker /* We only add symbol tables for ELF files. It makes not much sense
216*7304104dSAndroid Build Coastguard Worker to add symbols from executables but we do so for compatibility.
217*7304104dSAndroid Build Coastguard Worker For DSOs and executables we use the dynamic symbol table, for
218*7304104dSAndroid Build Coastguard Worker relocatable files all the DT_SYMTAB tables. */
219*7304104dSAndroid Build Coastguard Worker if (elf_kind (elf) != ELF_K_ELF)
220*7304104dSAndroid Build Coastguard Worker return;
221*7304104dSAndroid Build Coastguard Worker
222*7304104dSAndroid Build Coastguard Worker GElf_Ehdr ehdr_mem;
223*7304104dSAndroid Build Coastguard Worker GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
224*7304104dSAndroid Build Coastguard Worker if (ehdr == NULL)
225*7304104dSAndroid Build Coastguard Worker error_exit (0, _("cannot read ELF header of %s(%s): %s"),
226*7304104dSAndroid Build Coastguard Worker arfname, membername, elf_errmsg (-1));
227*7304104dSAndroid Build Coastguard Worker
228*7304104dSAndroid Build Coastguard Worker GElf_Word symtype;
229*7304104dSAndroid Build Coastguard Worker if (ehdr->e_type == ET_REL)
230*7304104dSAndroid Build Coastguard Worker symtype = SHT_SYMTAB;
231*7304104dSAndroid Build Coastguard Worker else if (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN)
232*7304104dSAndroid Build Coastguard Worker symtype = SHT_DYNSYM;
233*7304104dSAndroid Build Coastguard Worker else
234*7304104dSAndroid Build Coastguard Worker /* We do not handle that type. */
235*7304104dSAndroid Build Coastguard Worker return;
236*7304104dSAndroid Build Coastguard Worker
237*7304104dSAndroid Build Coastguard Worker /* Iterate over all sections. */
238*7304104dSAndroid Build Coastguard Worker Elf_Scn *scn = NULL;
239*7304104dSAndroid Build Coastguard Worker while ((scn = elf_nextscn (elf, scn)) != NULL)
240*7304104dSAndroid Build Coastguard Worker {
241*7304104dSAndroid Build Coastguard Worker /* Get the section header. */
242*7304104dSAndroid Build Coastguard Worker GElf_Shdr shdr_mem;
243*7304104dSAndroid Build Coastguard Worker GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
244*7304104dSAndroid Build Coastguard Worker if (shdr == NULL)
245*7304104dSAndroid Build Coastguard Worker continue;
246*7304104dSAndroid Build Coastguard Worker
247*7304104dSAndroid Build Coastguard Worker if (shdr->sh_type != symtype)
248*7304104dSAndroid Build Coastguard Worker continue;
249*7304104dSAndroid Build Coastguard Worker
250*7304104dSAndroid Build Coastguard Worker Elf_Data *data = elf_getdata (scn, NULL);
251*7304104dSAndroid Build Coastguard Worker if (data == NULL)
252*7304104dSAndroid Build Coastguard Worker continue;
253*7304104dSAndroid Build Coastguard Worker
254*7304104dSAndroid Build Coastguard Worker if (shdr->sh_entsize == 0)
255*7304104dSAndroid Build Coastguard Worker continue;
256*7304104dSAndroid Build Coastguard Worker
257*7304104dSAndroid Build Coastguard Worker int nsyms = shdr->sh_size / shdr->sh_entsize;
258*7304104dSAndroid Build Coastguard Worker for (int ndx = shdr->sh_info; ndx < nsyms; ++ndx)
259*7304104dSAndroid Build Coastguard Worker {
260*7304104dSAndroid Build Coastguard Worker GElf_Sym sym_mem;
261*7304104dSAndroid Build Coastguard Worker GElf_Sym *sym = gelf_getsym (data, ndx, &sym_mem);
262*7304104dSAndroid Build Coastguard Worker if (sym == NULL)
263*7304104dSAndroid Build Coastguard Worker continue;
264*7304104dSAndroid Build Coastguard Worker
265*7304104dSAndroid Build Coastguard Worker /* Ignore undefined symbols. */
266*7304104dSAndroid Build Coastguard Worker if (sym->st_shndx == SHN_UNDEF)
267*7304104dSAndroid Build Coastguard Worker continue;
268*7304104dSAndroid Build Coastguard Worker
269*7304104dSAndroid Build Coastguard Worker /* Use this symbol. */
270*7304104dSAndroid Build Coastguard Worker const char *symname = elf_strptr (elf, shdr->sh_link, sym->st_name);
271*7304104dSAndroid Build Coastguard Worker if (symname != NULL)
272*7304104dSAndroid Build Coastguard Worker arlib_add_symref (symname, off);
273*7304104dSAndroid Build Coastguard Worker }
274*7304104dSAndroid Build Coastguard Worker
275*7304104dSAndroid Build Coastguard Worker /* Only relocatable files can have more than one symbol table. */
276*7304104dSAndroid Build Coastguard Worker if (ehdr->e_type != ET_REL)
277*7304104dSAndroid Build Coastguard Worker break;
278*7304104dSAndroid Build Coastguard Worker }
279*7304104dSAndroid Build Coastguard Worker }
280