daily update
[binutils.git] / bfd / elf32-msp430.c
blob306a79889bcb46e00835a260813c0bfce4297bb8
1 /* MSP430-specific support for 32-bit ELF
2 Copyright (C) 2002, 2003 Free Software Foundation, Inc.
3 Contributed by Dmitry Diky <diwil@mail.ru>
5 This file is part of BFD, the Binary File Descriptor library.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21 #include "bfd.h"
22 #include "sysdep.h"
23 #include "libiberty.h"
24 #include "libbfd.h"
25 #include "elf-bfd.h"
26 #include "elf/msp430.h"
28 static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
29 PARAMS ((bfd *, bfd_reloc_code_real_type));
31 static void msp430_info_to_howto_rela
32 PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
34 static asection *elf32_msp430_gc_mark_hook
35 PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
36 struct elf_link_hash_entry *, Elf_Internal_Sym *));
38 static bfd_boolean elf32_msp430_gc_sweep_hook
39 PARAMS ((bfd *, struct bfd_link_info *, asection *,
40 const Elf_Internal_Rela *));
42 static bfd_boolean elf32_msp430_check_relocs
43 PARAMS ((bfd *, struct bfd_link_info *, asection *,
44 const Elf_Internal_Rela *));
46 static bfd_reloc_status_type msp430_final_link_relocate
47 PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
48 Elf_Internal_Rela *, bfd_vma));
50 static bfd_boolean elf32_msp430_relocate_section
51 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
52 Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
54 static void bfd_elf_msp430_final_write_processing
55 PARAMS ((bfd *, bfd_boolean));
57 static bfd_boolean elf32_msp430_object_p
58 PARAMS ((bfd *));
60 static void elf32_msp430_post_process_headers
61 PARAMS ((bfd *, struct bfd_link_info *));
63 /* Use RELA instead of REL. */
64 #undef USE_REL
66 static reloc_howto_type elf_msp430_howto_table[] =
68 HOWTO (R_MSP430_NONE, /* type */
69 0, /* rightshift */
70 2, /* size (0 = byte, 1 = short, 2 = long) */
71 32, /* bitsize */
72 FALSE, /* pc_relative */
73 0, /* bitpos */
74 complain_overflow_bitfield, /* complain_on_overflow */
75 bfd_elf_generic_reloc, /* special_function */
76 "R_MSP430_NONE", /* name */
77 FALSE, /* partial_inplace */
78 0, /* src_mask */
79 0, /* dst_mask */
80 FALSE), /* pcrel_offset */
82 HOWTO (R_MSP430_32, /* type */
83 0, /* rightshift */
84 2, /* size (0 = byte, 1 = short, 2 = long) */
85 32, /* bitsize */
86 FALSE, /* pc_relative */
87 0, /* bitpos */
88 complain_overflow_bitfield, /* complain_on_overflow */
89 bfd_elf_generic_reloc, /* special_function */
90 "R_MSP430_32", /* name */
91 FALSE, /* partial_inplace */
92 0xffffffff, /* src_mask */
93 0xffffffff, /* dst_mask */
94 FALSE), /* pcrel_offset */
96 /* A 13 bit PC relative relocation. */
97 HOWTO (R_MSP430_10_PCREL, /* type */
98 1, /* rightshift */
99 1, /* size (0 = byte, 1 = short, 2 = long) */
100 10, /* bitsize */
101 TRUE, /* pc_relative */
102 0, /* bitpos */
103 complain_overflow_bitfield, /* complain_on_overflow */
104 bfd_elf_generic_reloc, /* special_function */
105 "R_MSP430_13_PCREL", /* name */
106 FALSE, /* partial_inplace */
107 0xfff, /* src_mask */
108 0xfff, /* dst_mask */
109 TRUE), /* pcrel_offset */
111 /* A 16 bit absolute relocation. */
112 HOWTO (R_MSP430_16, /* type */
113 0, /* rightshift */
114 1, /* size (0 = byte, 1 = short, 2 = long) */
115 16, /* bitsize */
116 FALSE, /* pc_relative */
117 0, /* bitpos */
118 complain_overflow_dont,/* complain_on_overflow */
119 bfd_elf_generic_reloc, /* special_function */
120 "R_MSP430_16", /* name */
121 FALSE, /* partial_inplace */
122 0xffff, /* src_mask */
123 0xffff, /* dst_mask */
124 FALSE), /* pcrel_offset */
126 /* A 16 bit absolute relocation for command address. */
127 HOWTO (R_MSP430_16_PCREL, /* type */
128 1, /* rightshift */
129 1, /* size (0 = byte, 1 = short, 2 = long) */
130 16, /* bitsize */
131 TRUE, /* pc_relative */
132 0, /* bitpos */
133 complain_overflow_dont,/* complain_on_overflow */
134 bfd_elf_generic_reloc, /* special_function */
135 "R_MSP430_16_PCREL", /* name */
136 FALSE, /* partial_inplace */
137 0xffff, /* src_mask */
138 0xffff, /* dst_mask */
139 TRUE), /* pcrel_offset */
141 /* A 16 bit absolute relocation, byte operations. */
142 HOWTO (R_MSP430_16_BYTE, /* type */
143 0, /* rightshift */
144 1, /* size (0 = byte, 1 = short, 2 = long) */
145 16, /* bitsize */
146 FALSE, /* pc_relative */
147 0, /* bitpos */
148 complain_overflow_dont,/* complain_on_overflow */
149 bfd_elf_generic_reloc, /* special_function */
150 "R_MSP430_16_BYTE", /* name */
151 FALSE, /* partial_inplace */
152 0xffff, /* src_mask */
153 0xffff, /* dst_mask */
154 FALSE), /* pcrel_offset */
156 /* A 16 bit absolute relocation for command address. */
157 HOWTO (R_MSP430_16_PCREL_BYTE,/* type */
158 1, /* rightshift */
159 1, /* size (0 = byte, 1 = short, 2 = long) */
160 16, /* bitsize */
161 TRUE, /* pc_relative */
162 0, /* bitpos */
163 complain_overflow_dont,/* complain_on_overflow */
164 bfd_elf_generic_reloc, /* special_function */
165 "R_MSP430_16_PCREL_BYTE", /* name */
166 FALSE, /* partial_inplace */
167 0xffff, /* src_mask */
168 0xffff, /* dst_mask */
169 TRUE) /* pcrel_offset */
172 /* Map BFD reloc types to MSP430 ELF reloc types. */
174 struct msp430_reloc_map
176 bfd_reloc_code_real_type bfd_reloc_val;
177 unsigned int elf_reloc_val;
180 static const struct msp430_reloc_map msp430_reloc_map[] =
182 {BFD_RELOC_NONE, R_MSP430_NONE},
183 {BFD_RELOC_32, R_MSP430_32},
184 {BFD_RELOC_MSP430_10_PCREL, R_MSP430_10_PCREL},
185 {BFD_RELOC_16, R_MSP430_16_BYTE},
186 {BFD_RELOC_MSP430_16_PCREL, R_MSP430_16_PCREL},
187 {BFD_RELOC_MSP430_16, R_MSP430_16},
188 {BFD_RELOC_MSP430_16_PCREL_BYTE, R_MSP430_16_PCREL_BYTE},
189 {BFD_RELOC_MSP430_16_BYTE, R_MSP430_16_BYTE}
192 static reloc_howto_type *
193 bfd_elf32_bfd_reloc_type_lookup (abfd, code)
194 bfd *abfd ATTRIBUTE_UNUSED;
195 bfd_reloc_code_real_type code;
197 unsigned int i;
199 for (i = 0; i < ARRAY_SIZE (msp430_reloc_map); i++)
200 if (msp430_reloc_map[i].bfd_reloc_val == code)
201 return &elf_msp430_howto_table[msp430_reloc_map[i].elf_reloc_val];
203 return NULL;
206 /* Set the howto pointer for an MSP430 ELF reloc. */
208 static void
209 msp430_info_to_howto_rela (abfd, cache_ptr, dst)
210 bfd *abfd ATTRIBUTE_UNUSED;
211 arelent *cache_ptr;
212 Elf_Internal_Rela *dst;
214 unsigned int r_type;
216 r_type = ELF32_R_TYPE (dst->r_info);
217 BFD_ASSERT (r_type < (unsigned int) R_MSP430_max);
218 cache_ptr->howto = &elf_msp430_howto_table[r_type];
221 static asection *
222 elf32_msp430_gc_mark_hook (sec, info, rel, h, sym)
223 asection *sec;
224 struct bfd_link_info *info ATTRIBUTE_UNUSED;
225 Elf_Internal_Rela *rel;
226 struct elf_link_hash_entry *h;
227 Elf_Internal_Sym *sym;
229 if (h != NULL)
231 switch (ELF32_R_TYPE (rel->r_info))
233 default:
234 switch (h->root.type)
236 case bfd_link_hash_defined:
237 case bfd_link_hash_defweak:
238 return h->root.u.def.section;
240 case bfd_link_hash_common:
241 return h->root.u.c.p->section;
243 default:
244 break;
248 else
249 return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
251 return NULL;
254 static bfd_boolean
255 elf32_msp430_gc_sweep_hook (abfd, info, sec, relocs)
256 bfd *abfd ATTRIBUTE_UNUSED;
257 struct bfd_link_info *info ATTRIBUTE_UNUSED;
258 asection *sec ATTRIBUTE_UNUSED;
259 const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
261 /* We don't use got and plt entries for msp430. */
262 return TRUE;
265 /* Look through the relocs for a section during the first phase.
266 Since we don't do .gots or .plts, we just need to consider the
267 virtual table relocs for gc. */
269 static bfd_boolean
270 elf32_msp430_check_relocs (abfd, info, sec, relocs)
271 bfd *abfd;
272 struct bfd_link_info *info;
273 asection *sec;
274 const Elf_Internal_Rela *relocs;
276 Elf_Internal_Shdr *symtab_hdr;
277 struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
278 const Elf_Internal_Rela *rel;
279 const Elf_Internal_Rela *rel_end;
281 if (info->relocatable)
282 return TRUE;
284 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
285 sym_hashes = elf_sym_hashes (abfd);
286 sym_hashes_end =
287 sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
288 if (!elf_bad_symtab (abfd))
289 sym_hashes_end -= symtab_hdr->sh_info;
291 rel_end = relocs + sec->reloc_count;
292 for (rel = relocs; rel < rel_end; rel++)
294 struct elf_link_hash_entry *h;
295 unsigned long r_symndx;
297 r_symndx = ELF32_R_SYM (rel->r_info);
298 if (r_symndx < symtab_hdr->sh_info)
299 h = NULL;
300 else
301 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
304 return TRUE;
307 /* Perform a single relocation. By default we use the standard BFD
308 routines, but a few relocs, we have to do them ourselves. */
310 static bfd_reloc_status_type
311 msp430_final_link_relocate (howto, input_bfd, input_section,
312 contents, rel, relocation)
313 reloc_howto_type *howto;
314 bfd *input_bfd;
315 asection *input_section;
316 bfd_byte *contents;
317 Elf_Internal_Rela *rel;
318 bfd_vma relocation;
320 bfd_reloc_status_type r = bfd_reloc_ok;
321 bfd_vma x;
322 bfd_signed_vma srel;
324 switch (howto->type)
326 case R_MSP430_10_PCREL:
327 contents += rel->r_offset;
328 srel = (bfd_signed_vma) relocation;
329 srel += rel->r_addend;
330 srel -= rel->r_offset;
331 srel -= 2; /* Branch instructions add 2 to the PC... */
332 srel -= (input_section->output_section->vma +
333 input_section->output_offset);
335 if (srel & 1)
336 return bfd_reloc_outofrange;
338 /* MSP430 addresses commands as words. */
339 srel >>= 1;
341 /* Check for an overflow. */
342 if (srel < -512 || srel > 511)
343 return bfd_reloc_overflow;
345 x = bfd_get_16 (input_bfd, contents);
346 x = (x & 0xfc00) | (srel & 0x3ff);
347 bfd_put_16 (input_bfd, x, contents);
348 break;
350 case R_MSP430_16_PCREL:
351 contents += rel->r_offset;
352 srel = (bfd_signed_vma) relocation;
353 srel += rel->r_addend;
354 srel -= rel->r_offset;
355 /* Only branch instructions add 2 to the PC... */
356 srel -= (input_section->output_section->vma +
357 input_section->output_offset);
359 if (srel & 1)
360 return bfd_reloc_outofrange;
362 bfd_put_16 (input_bfd, srel & 0xffff, contents);
363 break;
365 case R_MSP430_16_PCREL_BYTE:
366 contents += rel->r_offset;
367 srel = (bfd_signed_vma) relocation;
368 srel += rel->r_addend;
369 srel -= rel->r_offset;
370 /* Only branch instructions add 2 to the PC... */
371 srel -= (input_section->output_section->vma +
372 input_section->output_offset);
374 bfd_put_16 (input_bfd, srel & 0xffff, contents);
375 break;
377 case R_MSP430_16_BYTE:
378 contents += rel->r_offset;
379 srel = (bfd_signed_vma) relocation;
380 srel += rel->r_addend;
381 bfd_put_16 (input_bfd, srel & 0xffff, contents);
382 break;
384 case R_MSP430_16:
385 contents += rel->r_offset;
386 srel = (bfd_signed_vma) relocation;
387 srel += rel->r_addend;
389 if (srel & 1)
390 return bfd_reloc_notsupported;
392 bfd_put_16 (input_bfd, srel & 0xffff, contents);
393 break;
395 default:
396 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
397 contents, rel->r_offset,
398 relocation, rel->r_addend);
401 return r;
404 /* Relocate an MSP430 ELF section. */
406 static bfd_boolean
407 elf32_msp430_relocate_section (output_bfd, info, input_bfd, input_section,
408 contents, relocs, local_syms, local_sections)
409 bfd *output_bfd ATTRIBUTE_UNUSED;
410 struct bfd_link_info *info;
411 bfd *input_bfd;
412 asection *input_section;
413 bfd_byte *contents;
414 Elf_Internal_Rela *relocs;
415 Elf_Internal_Sym *local_syms;
416 asection **local_sections;
418 Elf_Internal_Shdr *symtab_hdr;
419 struct elf_link_hash_entry **sym_hashes;
420 Elf_Internal_Rela *rel;
421 Elf_Internal_Rela *relend;
423 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
424 sym_hashes = elf_sym_hashes (input_bfd);
425 relend = relocs + input_section->reloc_count;
427 for (rel = relocs; rel < relend; rel++)
429 reloc_howto_type *howto;
430 unsigned long r_symndx;
431 Elf_Internal_Sym *sym;
432 asection *sec;
433 struct elf_link_hash_entry *h;
434 bfd_vma relocation;
435 bfd_reloc_status_type r;
436 const char *name = NULL;
437 int r_type;
439 /* This is a final link. */
441 r_type = ELF32_R_TYPE (rel->r_info);
442 r_symndx = ELF32_R_SYM (rel->r_info);
443 howto = elf_msp430_howto_table + ELF32_R_TYPE (rel->r_info);
444 h = NULL;
445 sym = NULL;
446 sec = NULL;
448 if (r_symndx < symtab_hdr->sh_info)
450 sym = local_syms + r_symndx;
451 sec = local_sections[r_symndx];
452 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
454 name = bfd_elf_string_from_elf_section
455 (input_bfd, symtab_hdr->sh_link, sym->st_name);
456 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
458 else
460 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
462 while (h->root.type == bfd_link_hash_indirect
463 || h->root.type == bfd_link_hash_warning)
464 h = (struct elf_link_hash_entry *) h->root.u.i.link;
466 name = h->root.root.string;
468 if (h->root.type == bfd_link_hash_defined
469 || h->root.type == bfd_link_hash_defweak)
471 sec = h->root.u.def.section;
472 relocation = (h->root.u.def.value
473 + sec->output_section->vma + sec->output_offset);
475 else if (h->root.type == bfd_link_hash_undefweak)
477 relocation = 0;
479 else
481 if (!((*info->callbacks->undefined_symbol)
482 (info, h->root.root.string, input_bfd,
483 input_section, rel->r_offset, TRUE)))
484 return FALSE;
485 relocation = 0;
489 r = msp430_final_link_relocate (howto, input_bfd, input_section,
490 contents, rel, relocation);
492 if (r != bfd_reloc_ok)
494 const char *msg = (const char *) NULL;
496 switch (r)
498 case bfd_reloc_overflow:
499 r = info->callbacks->reloc_overflow
500 (info, name, howto->name, (bfd_vma) 0,
501 input_bfd, input_section, rel->r_offset);
502 break;
504 case bfd_reloc_undefined:
505 r = info->callbacks->undefined_symbol
506 (info, name, input_bfd, input_section, rel->r_offset, TRUE);
507 break;
509 case bfd_reloc_outofrange:
510 msg = _("internal error: out of range error");
511 break;
513 case bfd_reloc_notsupported:
514 msg = _("internal error: unsupported relocation error");
515 break;
517 case bfd_reloc_dangerous:
518 msg = _("internal error: dangerous relocation");
519 break;
521 default:
522 msg = _("internal error: unknown error");
523 break;
526 if (msg)
527 r = info->callbacks->warning
528 (info, msg, name, input_bfd, input_section, rel->r_offset);
530 if (!r)
531 return FALSE;
536 return TRUE;
539 /* The final processing done just before writing out a MSP430 ELF object
540 file. This gets the MSP430 architecture right based on the machine
541 number. */
543 static void
544 bfd_elf_msp430_final_write_processing (abfd, linker)
545 bfd *abfd;
546 bfd_boolean linker ATTRIBUTE_UNUSED;
548 unsigned long val;
550 switch (bfd_get_mach (abfd))
552 default:
553 case bfd_mach_msp110:
554 val = E_MSP430_MACH_MSP430x11x1;
555 break;
557 case bfd_mach_msp11:
558 val = E_MSP430_MACH_MSP430x11;
559 break;
561 case bfd_mach_msp12:
562 val = E_MSP430_MACH_MSP430x12;
563 break;
565 case bfd_mach_msp13:
566 val = E_MSP430_MACH_MSP430x13;
567 break;
569 case bfd_mach_msp14:
570 val = E_MSP430_MACH_MSP430x14;
571 break;
573 case bfd_mach_msp15:
574 val = E_MSP430_MACH_MSP430x15;
575 break;
577 case bfd_mach_msp16:
578 val = E_MSP430_MACH_MSP430x16;
579 break;
581 case bfd_mach_msp31:
582 val = E_MSP430_MACH_MSP430x31;
583 break;
585 case bfd_mach_msp32:
586 val = E_MSP430_MACH_MSP430x32;
587 break;
589 case bfd_mach_msp33:
590 val = E_MSP430_MACH_MSP430x33;
591 break;
593 case bfd_mach_msp41:
594 val = E_MSP430_MACH_MSP430x41;
595 break;
597 case bfd_mach_msp42:
598 val = E_MSP430_MACH_MSP430x42;
599 break;
601 case bfd_mach_msp43:
602 val = E_MSP430_MACH_MSP430x43;
603 break;
605 case bfd_mach_msp44:
606 val = E_MSP430_MACH_MSP430x44;
607 break;
610 elf_elfheader (abfd)->e_machine = EM_MSP430;
611 elf_elfheader (abfd)->e_flags &= ~EF_MSP430_MACH;
612 elf_elfheader (abfd)->e_flags |= val;
615 /* Set the right machine number. */
617 static bfd_boolean
618 elf32_msp430_object_p (abfd)
619 bfd *abfd;
621 int e_set = bfd_mach_msp14;
623 if (elf_elfheader (abfd)->e_machine == EM_MSP430
624 || elf_elfheader (abfd)->e_machine == EM_MSP430_OLD)
626 int e_mach = elf_elfheader (abfd)->e_flags & EF_MSP430_MACH;
628 switch (e_mach)
630 default:
631 case E_MSP430_MACH_MSP430x11:
632 e_set = bfd_mach_msp11;
633 break;
635 case E_MSP430_MACH_MSP430x11x1:
636 e_set = bfd_mach_msp110;
637 break;
639 case E_MSP430_MACH_MSP430x12:
640 e_set = bfd_mach_msp12;
641 break;
643 case E_MSP430_MACH_MSP430x13:
644 e_set = bfd_mach_msp13;
645 break;
647 case E_MSP430_MACH_MSP430x14:
648 e_set = bfd_mach_msp14;
649 break;
651 case E_MSP430_MACH_MSP430x15:
652 e_set = bfd_mach_msp15;
653 break;
655 case E_MSP430_MACH_MSP430x16:
656 e_set = bfd_mach_msp16;
657 break;
659 case E_MSP430_MACH_MSP430x31:
660 e_set = bfd_mach_msp31;
661 break;
663 case E_MSP430_MACH_MSP430x32:
664 e_set = bfd_mach_msp32;
665 break;
667 case E_MSP430_MACH_MSP430x33:
668 e_set = bfd_mach_msp33;
669 break;
671 case E_MSP430_MACH_MSP430x41:
672 e_set = bfd_mach_msp41;
673 break;
675 case E_MSP430_MACH_MSP430x42:
676 e_set = bfd_mach_msp42;
677 break;
679 case E_MSP430_MACH_MSP430x43:
680 e_set = bfd_mach_msp43;
681 break;
683 case E_MSP430_MACH_MSP430x44:
684 e_set = bfd_mach_msp44;
685 break;
689 return bfd_default_set_arch_mach (abfd, bfd_arch_msp430, e_set);
692 static void
693 elf32_msp430_post_process_headers (abfd, link_info)
694 bfd *abfd;
695 struct bfd_link_info *link_info ATTRIBUTE_UNUSED;
697 Elf_Internal_Ehdr *i_ehdrp; /* ELF file header, internal form. */
699 i_ehdrp = elf_elfheader (abfd);
701 #ifndef ELFOSABI_STANDALONE
702 #define ELFOSABI_STANDALONE 255
703 #endif
705 i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_STANDALONE;
709 #define ELF_ARCH bfd_arch_msp430
710 #define ELF_MACHINE_CODE EM_MSP430
711 #define ELF_MACHINE_ALT1 EM_MSP430_OLD
712 #define ELF_MAXPAGESIZE 1
714 #define TARGET_LITTLE_SYM bfd_elf32_msp430_vec
715 #define TARGET_LITTLE_NAME "elf32-msp430"
717 #define elf_info_to_howto msp430_info_to_howto_rela
718 #define elf_info_to_howto_rel NULL
719 #define elf_backend_relocate_section elf32_msp430_relocate_section
720 #define elf_backend_gc_mark_hook elf32_msp430_gc_mark_hook
721 #define elf_backend_gc_sweep_hook elf32_msp430_gc_sweep_hook
722 #define elf_backend_check_relocs elf32_msp430_check_relocs
723 #define elf_backend_can_gc_sections 1
724 #define elf_backend_final_write_processing bfd_elf_msp430_final_write_processing
725 #define elf_backend_object_p elf32_msp430_object_p
726 #define elf_backend_post_process_headers elf32_msp430_post_process_headers
728 #include "elf32-target.h"