138889Sjdp/* ehopt.c--optimize gcc exception frame information. 2218822Sdim Copyright 1998, 2000, 2001, 2003, 2005 Free Software Foundation, Inc. 338889Sjdp Written by Ian Lance Taylor <ian@cygnus.com>. 438889Sjdp 538889SjdpThis file is part of GAS, the GNU Assembler. 638889Sjdp 738889SjdpGAS is free software; you can redistribute it and/or modify 838889Sjdpit under the terms of the GNU General Public License as published by 938889Sjdpthe Free Software Foundation; either version 2, or (at your option) 1038889Sjdpany later version. 1138889Sjdp 1238889SjdpGAS is distributed in the hope that it will be useful, 1338889Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of 1438889SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1538889SjdpGNU General Public License for more details. 1638889Sjdp 1738889SjdpYou should have received a copy of the GNU General Public License 1838889Sjdpalong with GAS; see the file COPYING. If not, write to the Free 19218822SdimSoftware Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 20218822Sdim02110-1301, USA. */ 2138889Sjdp 2238889Sjdp#include "as.h" 2338889Sjdp#include "subsegs.h" 2438889Sjdp 2538889Sjdp/* We include this ELF file, even though we may not be assembling for 2638889Sjdp ELF, since the exception frame information is always in a format 2738889Sjdp derived from DWARF. */ 2838889Sjdp 2938889Sjdp#include "elf/dwarf2.h" 3038889Sjdp 3138889Sjdp/* Try to optimize gcc 2.8 exception frame information. 3238889Sjdp 3338889Sjdp Exception frame information is emitted for every function in the 3477298Sobrien .eh_frame or .debug_frame sections. Simple information for a function 3577298Sobrien with no exceptions looks like this: 3638889Sjdp 3738889Sjdp__FRAME_BEGIN__: 3838889Sjdp .4byte .LLCIE1 / Length of Common Information Entry 3938889Sjdp.LSCIE1: 4077298Sobrien#if .eh_frame 4138889Sjdp .4byte 0x0 / CIE Identifier Tag 4277298Sobrien#elif .debug_frame 4377298Sobrien .4byte 0xffffffff / CIE Identifier Tag 4477298Sobrien#endif 4538889Sjdp .byte 0x1 / CIE Version 4638889Sjdp .byte 0x0 / CIE Augmentation (none) 4738889Sjdp .byte 0x1 / ULEB128 0x1 (CIE Code Alignment Factor) 4838889Sjdp .byte 0x7c / SLEB128 -4 (CIE Data Alignment Factor) 4938889Sjdp .byte 0x8 / CIE RA Column 5038889Sjdp .byte 0xc / DW_CFA_def_cfa 5138889Sjdp .byte 0x4 / ULEB128 0x4 5238889Sjdp .byte 0x4 / ULEB128 0x4 5338889Sjdp .byte 0x88 / DW_CFA_offset, column 0x8 5438889Sjdp .byte 0x1 / ULEB128 0x1 5538889Sjdp .align 4 5638889Sjdp.LECIE1: 5738889Sjdp .set .LLCIE1,.LECIE1-.LSCIE1 / CIE Length Symbol 5838889Sjdp .4byte .LLFDE1 / FDE Length 5938889Sjdp.LSFDE1: 6038889Sjdp .4byte .LSFDE1-__FRAME_BEGIN__ / FDE CIE offset 6138889Sjdp .4byte .LFB1 / FDE initial location 6238889Sjdp .4byte .LFE1-.LFB1 / FDE address range 6338889Sjdp .byte 0x4 / DW_CFA_advance_loc4 6438889Sjdp .4byte .LCFI0-.LFB1 6538889Sjdp .byte 0xe / DW_CFA_def_cfa_offset 6638889Sjdp .byte 0x8 / ULEB128 0x8 6738889Sjdp .byte 0x85 / DW_CFA_offset, column 0x5 6838889Sjdp .byte 0x2 / ULEB128 0x2 6938889Sjdp .byte 0x4 / DW_CFA_advance_loc4 7038889Sjdp .4byte .LCFI1-.LCFI0 7138889Sjdp .byte 0xd / DW_CFA_def_cfa_register 7238889Sjdp .byte 0x5 / ULEB128 0x5 7338889Sjdp .byte 0x4 / DW_CFA_advance_loc4 7438889Sjdp .4byte .LCFI2-.LCFI1 7538889Sjdp .byte 0x2e / DW_CFA_GNU_args_size 7638889Sjdp .byte 0x4 / ULEB128 0x4 7738889Sjdp .byte 0x4 / DW_CFA_advance_loc4 7838889Sjdp .4byte .LCFI3-.LCFI2 7938889Sjdp .byte 0x2e / DW_CFA_GNU_args_size 8038889Sjdp .byte 0x0 / ULEB128 0x0 8138889Sjdp .align 4 8238889Sjdp.LEFDE1: 8338889Sjdp .set .LLFDE1,.LEFDE1-.LSFDE1 / FDE Length Symbol 8438889Sjdp 8538889Sjdp The immediate issue we can address in the assembler is the 8638889Sjdp DW_CFA_advance_loc4 followed by a four byte value. The value is 8738889Sjdp the difference of two addresses in the function. Since gcc does 8838889Sjdp not know this value, it always uses four bytes. We will know the 8938889Sjdp value at the end of assembly, so we can do better. */ 9038889Sjdp 9178828Sobrienstruct cie_info 9278828Sobrien{ 9378828Sobrien unsigned code_alignment; 9478828Sobrien int z_augmentation; 9578828Sobrien}; 9638889Sjdp 97130561Sobrienstatic int get_cie_info (struct cie_info *); 9838889Sjdp 9978828Sobrien/* Extract information from the CIE. */ 10078828Sobrien 10138889Sjdpstatic int 102130561Sobrienget_cie_info (struct cie_info *info) 10338889Sjdp{ 10438889Sjdp fragS *f; 10538889Sjdp fixS *fix; 10638889Sjdp int offset; 10777298Sobrien char CIE_id; 10838889Sjdp char augmentation[10]; 10938889Sjdp int iaug; 11078828Sobrien int code_alignment = 0; 11138889Sjdp 11277298Sobrien /* We should find the CIE at the start of the section. */ 11377298Sobrien 11438889Sjdp f = seg_info (now_seg)->frchainP->frch_root; 11538889Sjdp fix = seg_info (now_seg)->frchainP->fix_root; 11638889Sjdp 11738889Sjdp /* Look through the frags of the section to find the code alignment. */ 11838889Sjdp 11977298Sobrien /* First make sure that the CIE Identifier Tag is 0/-1. */ 12038889Sjdp 12177298Sobrien if (strcmp (segment_name (now_seg), ".debug_frame") == 0) 12277298Sobrien CIE_id = (char)0xff; 12377298Sobrien else 12477298Sobrien CIE_id = 0; 12577298Sobrien 12638889Sjdp offset = 4; 12738889Sjdp while (f != NULL && offset >= f->fr_fix) 12838889Sjdp { 12938889Sjdp offset -= f->fr_fix; 13038889Sjdp f = f->fr_next; 13138889Sjdp } 13238889Sjdp if (f == NULL 13338889Sjdp || f->fr_fix - offset < 4 13477298Sobrien || f->fr_literal[offset] != CIE_id 13577298Sobrien || f->fr_literal[offset + 1] != CIE_id 13677298Sobrien || f->fr_literal[offset + 2] != CIE_id 13777298Sobrien || f->fr_literal[offset + 3] != CIE_id) 13878828Sobrien return 0; 13938889Sjdp 14038889Sjdp /* Next make sure the CIE version number is 1. */ 14138889Sjdp 14238889Sjdp offset += 4; 14338889Sjdp while (f != NULL && offset >= f->fr_fix) 14438889Sjdp { 14538889Sjdp offset -= f->fr_fix; 14638889Sjdp f = f->fr_next; 14738889Sjdp } 14838889Sjdp if (f == NULL 14938889Sjdp || f->fr_fix - offset < 1 15038889Sjdp || f->fr_literal[offset] != 1) 15178828Sobrien return 0; 15238889Sjdp 15338889Sjdp /* Skip the augmentation (a null terminated string). */ 15438889Sjdp 15538889Sjdp iaug = 0; 15638889Sjdp ++offset; 15738889Sjdp while (1) 15838889Sjdp { 15938889Sjdp while (f != NULL && offset >= f->fr_fix) 16038889Sjdp { 16138889Sjdp offset -= f->fr_fix; 16238889Sjdp f = f->fr_next; 16338889Sjdp } 16438889Sjdp if (f == NULL) 16578828Sobrien return 0; 16678828Sobrien 16738889Sjdp while (offset < f->fr_fix && f->fr_literal[offset] != '\0') 16838889Sjdp { 16938889Sjdp if ((size_t) iaug < (sizeof augmentation) - 1) 17038889Sjdp { 17138889Sjdp augmentation[iaug] = f->fr_literal[offset]; 17238889Sjdp ++iaug; 17338889Sjdp } 17438889Sjdp ++offset; 17538889Sjdp } 17638889Sjdp if (offset < f->fr_fix) 17738889Sjdp break; 17838889Sjdp } 17938889Sjdp ++offset; 18038889Sjdp while (f != NULL && offset >= f->fr_fix) 18138889Sjdp { 18238889Sjdp offset -= f->fr_fix; 18338889Sjdp f = f->fr_next; 18438889Sjdp } 18538889Sjdp if (f == NULL) 18678828Sobrien return 0; 18738889Sjdp 18838889Sjdp augmentation[iaug] = '\0'; 18938889Sjdp if (augmentation[0] == '\0') 19038889Sjdp { 19138889Sjdp /* No augmentation. */ 19238889Sjdp } 19338889Sjdp else if (strcmp (augmentation, "eh") == 0) 19438889Sjdp { 19538889Sjdp /* We have to skip a pointer. Unfortunately, we don't know how 19638889Sjdp large it is. We find out by looking for a matching fixup. */ 19738889Sjdp while (fix != NULL 19838889Sjdp && (fix->fx_frag != f || fix->fx_where != offset)) 19938889Sjdp fix = fix->fx_next; 20038889Sjdp if (fix == NULL) 20138889Sjdp offset += 4; 20238889Sjdp else 20338889Sjdp offset += fix->fx_size; 20438889Sjdp while (f != NULL && offset >= f->fr_fix) 20538889Sjdp { 20638889Sjdp offset -= f->fr_fix; 20738889Sjdp f = f->fr_next; 20838889Sjdp } 20938889Sjdp if (f == NULL) 21078828Sobrien return 0; 21138889Sjdp } 21278828Sobrien else if (augmentation[0] != 'z') 21378828Sobrien return 0; 21438889Sjdp 21538889Sjdp /* We're now at the code alignment factor, which is a ULEB128. If 21638889Sjdp it isn't a single byte, forget it. */ 21738889Sjdp 21838889Sjdp code_alignment = f->fr_literal[offset] & 0xff; 21978828Sobrien if ((code_alignment & 0x80) != 0) 22078828Sobrien code_alignment = 0; 22138889Sjdp 22278828Sobrien info->code_alignment = code_alignment; 22378828Sobrien info->z_augmentation = (augmentation[0] == 'z'); 22478828Sobrien 22578828Sobrien return 1; 22638889Sjdp} 22738889Sjdp 22838889Sjdp/* This function is called from emit_expr. It looks for cases which 22938889Sjdp we can optimize. 23038889Sjdp 23138889Sjdp Rather than try to parse all this information as we read it, we 23238889Sjdp look for a single byte DW_CFA_advance_loc4 followed by a 4 byte 23338889Sjdp difference. We turn that into a rs_cfa_advance frag, and handle 23438889Sjdp those frags at the end of the assembly. If the gcc output changes 23538889Sjdp somewhat, this optimization may stop working. 23638889Sjdp 23738889Sjdp This function returns non-zero if it handled the expression and 23838889Sjdp emit_expr should not do anything, or zero otherwise. It can also 23938889Sjdp change *EXP and *PNBYTES. */ 24038889Sjdp 24138889Sjdpint 242130561Sobriencheck_eh_frame (expressionS *exp, unsigned int *pnbytes) 24338889Sjdp{ 24477298Sobrien struct frame_data 24577298Sobrien { 24678828Sobrien enum frame_state 24778828Sobrien { 24878828Sobrien state_idle, 24978828Sobrien state_saw_size, 25078828Sobrien state_saw_cie_offset, 25178828Sobrien state_saw_pc_begin, 25278828Sobrien state_seeing_aug_size, 25378828Sobrien state_skipping_aug, 25478828Sobrien state_wait_loc4, 25578828Sobrien state_saw_loc4, 25678828Sobrien state_error, 25778828Sobrien } state; 25878828Sobrien 25978828Sobrien int cie_info_ok; 26078828Sobrien struct cie_info cie_info; 26178828Sobrien 26277298Sobrien symbolS *size_end_sym; 26377298Sobrien fragS *loc4_frag; 26477298Sobrien int loc4_fix; 26578828Sobrien 26678828Sobrien int aug_size; 26778828Sobrien int aug_shift; 26877298Sobrien }; 26938889Sjdp 27077298Sobrien static struct frame_data eh_frame_data; 27177298Sobrien static struct frame_data debug_frame_data; 27277298Sobrien struct frame_data *d; 27377298Sobrien 27477298Sobrien /* Don't optimize. */ 27577298Sobrien if (flag_traditional_format) 27677298Sobrien return 0; 27777298Sobrien 27877298Sobrien /* Select the proper section data. */ 27977298Sobrien if (strcmp (segment_name (now_seg), ".eh_frame") == 0) 28077298Sobrien d = &eh_frame_data; 28177298Sobrien else if (strcmp (segment_name (now_seg), ".debug_frame") == 0) 28277298Sobrien d = &debug_frame_data; 28377298Sobrien else 28477298Sobrien return 0; 28577298Sobrien 28678828Sobrien if (d->state >= state_saw_size && S_IS_DEFINED (d->size_end_sym)) 28756944Sobrien { 28856944Sobrien /* We have come to the end of the CIE or FDE. See below where 28956944Sobrien we set saw_size. We must check this first because we may now 29056944Sobrien be looking at the next size. */ 29178828Sobrien d->state = state_idle; 29256944Sobrien } 29356944Sobrien 29478828Sobrien switch (d->state) 29538889Sjdp { 29678828Sobrien case state_idle: 29778828Sobrien if (*pnbytes == 4) 29856944Sobrien { 29978828Sobrien /* This might be the size of the CIE or FDE. We want to know 30078828Sobrien the size so that we don't accidentally optimize across an FDE 30178828Sobrien boundary. We recognize the size in one of two forms: a 30278828Sobrien symbol which will later be defined as a difference, or a 30378828Sobrien subtraction of two symbols. Either way, we can tell when we 30478828Sobrien are at the end of the FDE because the symbol becomes defined 30578828Sobrien (in the case of a subtraction, the end symbol, from which the 30678828Sobrien start symbol is being subtracted). Other ways of describing 30778828Sobrien the size will not be optimized. */ 30878828Sobrien if ((exp->X_op == O_symbol || exp->X_op == O_subtract) 30978828Sobrien && ! S_IS_DEFINED (exp->X_add_symbol)) 31078828Sobrien { 31178828Sobrien d->state = state_saw_size; 31278828Sobrien d->size_end_sym = exp->X_add_symbol; 31378828Sobrien } 31456944Sobrien } 31578828Sobrien break; 31638889Sjdp 31778828Sobrien case state_saw_size: 31878828Sobrien case state_saw_cie_offset: 31978828Sobrien /* Assume whatever form it appears in, it appears atomically. */ 32078828Sobrien d->state += 1; 32178828Sobrien break; 32238889Sjdp 32378828Sobrien case state_saw_pc_begin: 32478828Sobrien /* Decide whether we should see an augmentation. */ 32578828Sobrien if (! d->cie_info_ok 32678828Sobrien && ! (d->cie_info_ok = get_cie_info (&d->cie_info))) 32778828Sobrien d->state = state_error; 32878828Sobrien else if (d->cie_info.z_augmentation) 32978828Sobrien { 33078828Sobrien d->state = state_seeing_aug_size; 33178828Sobrien d->aug_size = 0; 33278828Sobrien d->aug_shift = 0; 33378828Sobrien } 33478828Sobrien else 33578828Sobrien d->state = state_wait_loc4; 33678828Sobrien break; 33738889Sjdp 33878828Sobrien case state_seeing_aug_size: 33978828Sobrien /* Bytes == -1 means this comes from an leb128 directive. */ 34078828Sobrien if ((int)*pnbytes == -1 && exp->X_op == O_constant) 34138889Sjdp { 34278828Sobrien d->aug_size = exp->X_add_number; 34378828Sobrien d->state = state_skipping_aug; 34438889Sjdp } 34578828Sobrien else if (*pnbytes == 1 && exp->X_op == O_constant) 34638889Sjdp { 34778828Sobrien unsigned char byte = exp->X_add_number; 34878828Sobrien d->aug_size |= (byte & 0x7f) << d->aug_shift; 34978828Sobrien d->aug_shift += 7; 35078828Sobrien if ((byte & 0x80) == 0) 35178828Sobrien d->state = state_skipping_aug; 35238889Sjdp } 35378828Sobrien else 35478828Sobrien d->state = state_error; 355130561Sobrien if (d->state == state_skipping_aug && d->aug_size == 0) 356130561Sobrien d->state = state_wait_loc4; 35778828Sobrien break; 35878828Sobrien 35978828Sobrien case state_skipping_aug: 36078828Sobrien if ((int)*pnbytes < 0) 36178828Sobrien d->state = state_error; 36278828Sobrien else 36338889Sjdp { 364104834Sobrien int left = (d->aug_size -= *pnbytes); 36578828Sobrien if (left == 0) 36678828Sobrien d->state = state_wait_loc4; 36778828Sobrien else if (left < 0) 36878828Sobrien d->state = state_error; 36938889Sjdp } 37078828Sobrien break; 37178828Sobrien 37278828Sobrien case state_wait_loc4: 37378828Sobrien if (*pnbytes == 1 37478828Sobrien && exp->X_op == O_constant 37578828Sobrien && exp->X_add_number == DW_CFA_advance_loc4) 37638889Sjdp { 37778828Sobrien /* This might be a DW_CFA_advance_loc4. Record the frag and the 37878828Sobrien position within the frag, so that we can change it later. */ 37978828Sobrien frag_grow (1); 38078828Sobrien d->state = state_saw_loc4; 38178828Sobrien d->loc4_frag = frag_now; 38278828Sobrien d->loc4_fix = frag_now_fix (); 38338889Sjdp } 38478828Sobrien break; 38538889Sjdp 38678828Sobrien case state_saw_loc4: 38778828Sobrien d->state = state_wait_loc4; 38878828Sobrien if (*pnbytes != 4) 38978828Sobrien break; 39078828Sobrien if (exp->X_op == O_constant) 39178828Sobrien { 39278828Sobrien /* This is a case which we can optimize. The two symbols being 39378828Sobrien subtracted were in the same frag and the expression was 39478828Sobrien reduced to a constant. We can do the optimization entirely 39578828Sobrien in this function. */ 39678828Sobrien if (d->cie_info.code_alignment > 0 39778828Sobrien && exp->X_add_number % d->cie_info.code_alignment == 0 39878828Sobrien && exp->X_add_number / d->cie_info.code_alignment < 0x40) 39978828Sobrien { 40078828Sobrien d->loc4_frag->fr_literal[d->loc4_fix] 40178828Sobrien = DW_CFA_advance_loc 40278828Sobrien | (exp->X_add_number / d->cie_info.code_alignment); 40378828Sobrien /* No more bytes needed. */ 40478828Sobrien return 1; 40578828Sobrien } 40678828Sobrien else if (exp->X_add_number < 0x100) 40778828Sobrien { 40878828Sobrien d->loc4_frag->fr_literal[d->loc4_fix] = DW_CFA_advance_loc1; 40978828Sobrien *pnbytes = 1; 41078828Sobrien } 41178828Sobrien else if (exp->X_add_number < 0x10000) 41278828Sobrien { 41378828Sobrien d->loc4_frag->fr_literal[d->loc4_fix] = DW_CFA_advance_loc2; 41478828Sobrien *pnbytes = 2; 41578828Sobrien } 41678828Sobrien } 41778828Sobrien else if (exp->X_op == O_subtract) 41878828Sobrien { 41978828Sobrien /* This is a case we can optimize. The expression was not 42078828Sobrien reduced, so we can not finish the optimization until the end 42178828Sobrien of the assembly. We set up a variant frag which we handle 42278828Sobrien later. */ 42378828Sobrien int fr_subtype; 42438889Sjdp 42578828Sobrien if (d->cie_info.code_alignment > 0) 42678828Sobrien fr_subtype = d->cie_info.code_alignment << 3; 42778828Sobrien else 42878828Sobrien fr_subtype = 0; 42938889Sjdp 43078828Sobrien frag_var (rs_cfa, 4, 0, fr_subtype, make_expr_symbol (exp), 43178828Sobrien d->loc4_fix, (char *) d->loc4_frag); 43278828Sobrien return 1; 43378828Sobrien } 43478828Sobrien break; 43578828Sobrien 43678828Sobrien case state_error: 43778828Sobrien /* Just skipping everything. */ 43878828Sobrien break; 43938889Sjdp } 44038889Sjdp 44138889Sjdp return 0; 44238889Sjdp} 44338889Sjdp 44438889Sjdp/* The function estimates the size of a rs_cfa variant frag based on 44538889Sjdp the current values of the symbols. It is called before the 44678828Sobrien relaxation loop. We set fr_subtype{0:2} to the expected length. */ 44738889Sjdp 44838889Sjdpint 449130561Sobrieneh_frame_estimate_size_before_relax (fragS *frag) 45038889Sjdp{ 45138889Sjdp offsetT diff; 45278828Sobrien int ca = frag->fr_subtype >> 3; 45338889Sjdp int ret; 45438889Sjdp 45589857Sobrien diff = resolve_symbol_value (frag->fr_symbol); 45638889Sjdp 45778828Sobrien if (ca > 0 && diff % ca == 0 && diff / ca < 0x40) 45838889Sjdp ret = 0; 45938889Sjdp else if (diff < 0x100) 46038889Sjdp ret = 1; 46138889Sjdp else if (diff < 0x10000) 46238889Sjdp ret = 2; 46338889Sjdp else 46438889Sjdp ret = 4; 46538889Sjdp 46678828Sobrien frag->fr_subtype = (frag->fr_subtype & ~7) | ret; 46738889Sjdp 46838889Sjdp return ret; 46938889Sjdp} 47038889Sjdp 47138889Sjdp/* This function relaxes a rs_cfa variant frag based on the current 47278828Sobrien values of the symbols. fr_subtype{0:2} is the current length of 47378828Sobrien the frag. This returns the change in frag length. */ 47438889Sjdp 47538889Sjdpint 476130561Sobrieneh_frame_relax_frag (fragS *frag) 47738889Sjdp{ 47838889Sjdp int oldsize, newsize; 47938889Sjdp 48078828Sobrien oldsize = frag->fr_subtype & 7; 48138889Sjdp newsize = eh_frame_estimate_size_before_relax (frag); 48238889Sjdp return newsize - oldsize; 48338889Sjdp} 48438889Sjdp 48538889Sjdp/* This function converts a rs_cfa variant frag into a normal fill 48638889Sjdp frag. This is called after all relaxation has been done. 48778828Sobrien fr_subtype{0:2} will be the desired length of the frag. */ 48838889Sjdp 48938889Sjdpvoid 490130561Sobrieneh_frame_convert_frag (fragS *frag) 49138889Sjdp{ 49238889Sjdp offsetT diff; 49338889Sjdp fragS *loc4_frag; 49438889Sjdp int loc4_fix; 49538889Sjdp 49638889Sjdp loc4_frag = (fragS *) frag->fr_opcode; 49738889Sjdp loc4_fix = (int) frag->fr_offset; 49838889Sjdp 49989857Sobrien diff = resolve_symbol_value (frag->fr_symbol); 50038889Sjdp 50178828Sobrien switch (frag->fr_subtype & 7) 50238889Sjdp { 50378828Sobrien case 0: 50478828Sobrien { 50578828Sobrien int ca = frag->fr_subtype >> 3; 50678828Sobrien assert (ca > 0 && diff % ca == 0 && diff / ca < 0x40); 50778828Sobrien loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc | (diff / ca); 50878828Sobrien } 50978828Sobrien break; 51038889Sjdp 51178828Sobrien case 1: 51238889Sjdp assert (diff < 0x100); 51338889Sjdp loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc1; 51438889Sjdp frag->fr_literal[frag->fr_fix] = diff; 51578828Sobrien break; 51678828Sobrien 51778828Sobrien case 2: 51838889Sjdp assert (diff < 0x10000); 51938889Sjdp loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc2; 52038889Sjdp md_number_to_chars (frag->fr_literal + frag->fr_fix, diff, 2); 52178828Sobrien break; 52278828Sobrien 52378828Sobrien default: 52478828Sobrien md_number_to_chars (frag->fr_literal + frag->fr_fix, diff, 4); 52578828Sobrien break; 52638889Sjdp } 52738889Sjdp 52878828Sobrien frag->fr_fix += frag->fr_subtype & 7; 52938889Sjdp frag->fr_type = rs_fill; 53078828Sobrien frag->fr_subtype = 0; 53138889Sjdp frag->fr_offset = 0; 53238889Sjdp} 533