ehopt.c revision 218822
1119418Sobrien/* ehopt.c--optimize gcc exception frame information. 2119418Sobrien Copyright 1998, 2000, 2001, 2003, 2005 Free Software Foundation, Inc. 393746Sjulian Written by Ian Lance Taylor <ian@cygnus.com>. 493746Sjulian 593746SjulianThis file is part of GAS, the GNU Assembler. 693746Sjulian 793746SjulianGAS is free software; you can redistribute it and/or modify 893746Sjulianit under the terms of the GNU General Public License as published by 993746Sjulianthe Free Software Foundation; either version 2, or (at your option) 1093746Sjulianany later version. 1193746Sjulian 1293746SjulianGAS is distributed in the hope that it will be useful, 1393746Sjulianbut WITHOUT ANY WARRANTY; without even the implied warranty of 1493746SjulianMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1593746SjulianGNU General Public License for more details. 1693746Sjulian 1793746SjulianYou should have received a copy of the GNU General Public License 1893746Sjulianalong with GAS; see the file COPYING. If not, write to the Free 1993746SjulianSoftware Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 2093746Sjulian02110-1301, USA. */ 2193746Sjulian 2293746Sjulian#include "as.h" 2393746Sjulian#include "subsegs.h" 2493746Sjulian 2593746Sjulian/* We include this ELF file, even though we may not be assembling for 2693746Sjulian ELF, since the exception frame information is always in a format 27119418Sobrien derived from DWARF. */ 2893746Sjulian 29113038Sobrien#include "elf/dwarf2.h" 30113038Sobrien 31113038Sobrien/* Try to optimize gcc 2.8 exception frame information. 32113038Sobrien 3393746Sjulian Exception frame information is emitted for every function in the 3493746Sjulian .eh_frame or .debug_frame sections. Simple information for a function 3593746Sjulian with no exceptions looks like this: 3693746Sjulian 3793746Sjulian__FRAME_BEGIN__: 3893746Sjulian .4byte .LLCIE1 / Length of Common Information Entry 3993746Sjulian.LSCIE1: 4093746Sjulian#if .eh_frame 4193746Sjulian .4byte 0x0 / CIE Identifier Tag 4293746Sjulian#elif .debug_frame 4393746Sjulian .4byte 0xffffffff / CIE Identifier Tag 4495807Sjulian#endif 4595807Sjulian .byte 0x1 / CIE Version 4693746Sjulian .byte 0x0 / CIE Augmentation (none) 4793746Sjulian .byte 0x1 / ULEB128 0x1 (CIE Code Alignment Factor) 4893746Sjulian .byte 0x7c / SLEB128 -4 (CIE Data Alignment Factor) 4993746Sjulian .byte 0x8 / CIE RA Column 5093746Sjulian .byte 0xc / DW_CFA_def_cfa 5193746Sjulian .byte 0x4 / ULEB128 0x4 5293746Sjulian .byte 0x4 / ULEB128 0x4 53147256Sbrooks .byte 0x88 / DW_CFA_offset, column 0x8 5493746Sjulian .byte 0x1 / ULEB128 0x1 5593746Sjulian .align 4 5693746Sjulian.LECIE1: 5793746Sjulian .set .LLCIE1,.LECIE1-.LSCIE1 / CIE Length Symbol 5893746Sjulian .4byte .LLFDE1 / FDE Length 5993746Sjulian.LSFDE1: 6093746Sjulian .4byte .LSFDE1-__FRAME_BEGIN__ / FDE CIE offset 6193746Sjulian .4byte .LFB1 / FDE initial location 6293746Sjulian .4byte .LFE1-.LFB1 / FDE address range 6393746Sjulian .byte 0x4 / DW_CFA_advance_loc4 64119285Simp .4byte .LCFI0-.LFB1 65119285Simp .byte 0xe / DW_CFA_def_cfa_offset 6693746Sjulian .byte 0x8 / ULEB128 0x8 6793746Sjulian .byte 0x85 / DW_CFA_offset, column 0x5 6893746Sjulian .byte 0x2 / ULEB128 0x2 6993746Sjulian .byte 0x4 / DW_CFA_advance_loc4 7093746Sjulian .4byte .LCFI1-.LCFI0 7193746Sjulian .byte 0xd / DW_CFA_def_cfa_register 7293746Sjulian .byte 0x5 / ULEB128 0x5 73153084Sru .byte 0x4 / DW_CFA_advance_loc4 7494904Sjulian .4byte .LCFI2-.LCFI1 7594904Sjulian .byte 0x2e / DW_CFA_GNU_args_size 7693746Sjulian .byte 0x4 / ULEB128 0x4 7794904Sjulian .byte 0x4 / DW_CFA_advance_loc4 7894904Sjulian .4byte .LCFI3-.LCFI2 7993746Sjulian .byte 0x2e / DW_CFA_GNU_args_size 8093746Sjulian .byte 0x0 / ULEB128 0x0 8193746Sjulian .align 4 8293746Sjulian.LEFDE1: 8393746Sjulian .set .LLFDE1,.LEFDE1-.LSFDE1 / FDE Length Symbol 8493746Sjulian 8593746Sjulian The immediate issue we can address in the assembler is the 86119285Simp DW_CFA_advance_loc4 followed by a four byte value. The value is 8793746Sjulian the difference of two addresses in the function. Since gcc does 8893746Sjulian not know this value, it always uses four bytes. We will know the 8993746Sjulian value at the end of assembly, so we can do better. */ 9093746Sjulian 9193746Sjulianstruct cie_info 9293746Sjulian{ 9393746Sjulian unsigned code_alignment; 9493746Sjulian int z_augmentation; 9593746Sjulian}; 9693746Sjulian 9793746Sjulianstatic int get_cie_info (struct cie_info *); 9893746Sjulian 9993746Sjulian/* Extract information from the CIE. */ 10093746Sjulian 10193746Sjulianstatic int 10293746Sjulianget_cie_info (struct cie_info *info) 10393746Sjulian{ 10493746Sjulian fragS *f; 10593746Sjulian fixS *fix; 10693746Sjulian int offset; 10793746Sjulian char CIE_id; 10893746Sjulian char augmentation[10]; 10993746Sjulian int iaug; 11093746Sjulian int code_alignment = 0; 11193746Sjulian 11293746Sjulian /* We should find the CIE at the start of the section. */ 11393746Sjulian 11493746Sjulian f = seg_info (now_seg)->frchainP->frch_root; 11593746Sjulian fix = seg_info (now_seg)->frchainP->fix_root; 11693746Sjulian 11793746Sjulian /* Look through the frags of the section to find the code alignment. */ 11893746Sjulian 11993746Sjulian /* First make sure that the CIE Identifier Tag is 0/-1. */ 12093746Sjulian 12193746Sjulian if (strcmp (segment_name (now_seg), ".debug_frame") == 0) 12293746Sjulian CIE_id = (char)0xff; 12393746Sjulian else 124149151Sjhb CIE_id = 0; 12593746Sjulian 12693746Sjulian offset = 4; 127149151Sjhb while (f != NULL && offset >= f->fr_fix) 12893746Sjulian { 12993746Sjulian offset -= f->fr_fix; 130188172Simp f = f->fr_next; 13193746Sjulian } 13293746Sjulian if (f == NULL 13393746Sjulian || f->fr_fix - offset < 4 13493746Sjulian || f->fr_literal[offset] != CIE_id 13593746Sjulian || f->fr_literal[offset + 1] != CIE_id 13693746Sjulian || f->fr_literal[offset + 2] != CIE_id 13793746Sjulian || f->fr_literal[offset + 3] != CIE_id) 13893746Sjulian return 0; 13993746Sjulian 14093746Sjulian /* Next make sure the CIE version number is 1. */ 14193746Sjulian 14293746Sjulian offset += 4; 14393746Sjulian while (f != NULL && offset >= f->fr_fix) 14493746Sjulian { 14593746Sjulian offset -= f->fr_fix; 146106696Salfred f = f->fr_next; 147106696Salfred } 14893746Sjulian if (f == NULL 14993746Sjulian || f->fr_fix - offset < 1 15093746Sjulian || f->fr_literal[offset] != 1) 15193746Sjulian return 0; 15293746Sjulian 15393746Sjulian /* Skip the augmentation (a null terminated string). */ 15493746Sjulian 15593746Sjulian iaug = 0; 15693746Sjulian ++offset; 15793746Sjulian while (1) 15893746Sjulian { 15993746Sjulian while (f != NULL && offset >= f->fr_fix) 16093746Sjulian { 16193746Sjulian offset -= f->fr_fix; 16293746Sjulian f = f->fr_next; 16393746Sjulian } 16493746Sjulian if (f == NULL) 16593746Sjulian return 0; 16693746Sjulian 167113506Smdodd while (offset < f->fr_fix && f->fr_literal[offset] != '\0') 168113506Smdodd { 169113506Smdodd if ((size_t) iaug < (sizeof augmentation) - 1) 17093746Sjulian { 17193746Sjulian augmentation[iaug] = f->fr_literal[offset]; 17293746Sjulian ++iaug; 17393746Sjulian } 17493746Sjulian ++offset; 17593746Sjulian } 17693746Sjulian if (offset < f->fr_fix) 17793746Sjulian break; 178149151Sjhb } 17993746Sjulian ++offset; 18093746Sjulian while (f != NULL && offset >= f->fr_fix) 18193746Sjulian { 18293746Sjulian offset -= f->fr_fix; 18393746Sjulian f = f->fr_next; 18493746Sjulian } 18593746Sjulian if (f == NULL) 18693746Sjulian return 0; 18793746Sjulian 18893746Sjulian augmentation[iaug] = '\0'; 18993746Sjulian if (augmentation[0] == '\0') 19093746Sjulian { 19193746Sjulian /* No augmentation. */ 19293746Sjulian } 19393746Sjulian else if (strcmp (augmentation, "eh") == 0) 19493746Sjulian { 19593746Sjulian /* We have to skip a pointer. Unfortunately, we don't know how 19693746Sjulian large it is. We find out by looking for a matching fixup. */ 19793746Sjulian while (fix != NULL 19893746Sjulian && (fix->fx_frag != f || fix->fx_where != offset)) 19993746Sjulian fix = fix->fx_next; 20093746Sjulian if (fix == NULL) 20193746Sjulian offset += 4; 20293746Sjulian else 20393746Sjulian offset += fix->fx_size; 20493746Sjulian while (f != NULL && offset >= f->fr_fix) 20593746Sjulian { 20693746Sjulian offset -= f->fr_fix; 20793746Sjulian f = f->fr_next; 20893746Sjulian } 20993746Sjulian if (f == NULL) 21093746Sjulian return 0; 21193746Sjulian } 21293746Sjulian else if (augmentation[0] != 'z') 21393746Sjulian return 0; 21493746Sjulian 21593746Sjulian /* We're now at the code alignment factor, which is a ULEB128. If 21693746Sjulian it isn't a single byte, forget it. */ 21793746Sjulian 21893746Sjulian code_alignment = f->fr_literal[offset] & 0xff; 21993746Sjulian if ((code_alignment & 0x80) != 0) 22093746Sjulian code_alignment = 0; 22193746Sjulian 22293746Sjulian info->code_alignment = code_alignment; 22393746Sjulian info->z_augmentation = (augmentation[0] == 'z'); 224148945Sjhb 22593746Sjulian return 1; 22693746Sjulian} 22793746Sjulian 22893746Sjulian/* This function is called from emit_expr. It looks for cases which 22993746Sjulian we can optimize. 230149151Sjhb 23193746Sjulian Rather than try to parse all this information as we read it, we 23293746Sjulian look for a single byte DW_CFA_advance_loc4 followed by a 4 byte 23393746Sjulian difference. We turn that into a rs_cfa_advance frag, and handle 23493746Sjulian those frags at the end of the assembly. If the gcc output changes 23593746Sjulian somewhat, this optimization may stop working. 23693746Sjulian 23793746Sjulian This function returns non-zero if it handled the expression and 23893746Sjulian emit_expr should not do anything, or zero otherwise. It can also 23993746Sjulian change *EXP and *PNBYTES. */ 24093746Sjulian 24193746Sjulianint 24293746Sjuliancheck_eh_frame (expressionS *exp, unsigned int *pnbytes) 24393746Sjulian{ 24493746Sjulian struct frame_data 24593746Sjulian { 24693746Sjulian enum frame_state 24793746Sjulian { 24893746Sjulian state_idle, 24993746Sjulian state_saw_size, 25093746Sjulian state_saw_cie_offset, 25193746Sjulian state_saw_pc_begin, 25293746Sjulian state_seeing_aug_size, 25393746Sjulian state_skipping_aug, 25493746Sjulian state_wait_loc4, 25593746Sjulian state_saw_loc4, 25693746Sjulian state_error, 25793746Sjulian } state; 25893746Sjulian 25993746Sjulian int cie_info_ok; 26093746Sjulian struct cie_info cie_info; 26193746Sjulian 26293746Sjulian symbolS *size_end_sym; 26393746Sjulian fragS *loc4_frag; 26493746Sjulian int loc4_fix; 26593746Sjulian 26693746Sjulian int aug_size; 26793746Sjulian int aug_shift; 26893746Sjulian }; 26993746Sjulian 27093746Sjulian static struct frame_data eh_frame_data; 27193746Sjulian static struct frame_data debug_frame_data; 27293746Sjulian struct frame_data *d; 27393746Sjulian 274149151Sjhb /* Don't optimize. */ 27593746Sjulian if (flag_traditional_format) 27693746Sjulian return 0; 27793746Sjulian 27893746Sjulian /* Select the proper section data. */ 27993746Sjulian if (strcmp (segment_name (now_seg), ".eh_frame") == 0) 28093746Sjulian d = &eh_frame_data; 28193746Sjulian else if (strcmp (segment_name (now_seg), ".debug_frame") == 0) 28293746Sjulian d = &debug_frame_data; 28393746Sjulian else 28493746Sjulian return 0; 28593746Sjulian 28693746Sjulian if (d->state >= state_saw_size && S_IS_DEFINED (d->size_end_sym)) 28793746Sjulian { 28893746Sjulian /* We have come to the end of the CIE or FDE. See below where 28993746Sjulian we set saw_size. We must check this first because we may now 29093746Sjulian be looking at the next size. */ 29193746Sjulian d->state = state_idle; 29293746Sjulian } 29393746Sjulian 29493746Sjulian switch (d->state) 29593746Sjulian { 29693746Sjulian case state_idle: 29793746Sjulian if (*pnbytes == 4) 29893746Sjulian { 29993746Sjulian /* This might be the size of the CIE or FDE. We want to know 30093746Sjulian the size so that we don't accidentally optimize across an FDE 30193746Sjulian boundary. We recognize the size in one of two forms: a 30293746Sjulian symbol which will later be defined as a difference, or a 30393746Sjulian subtraction of two symbols. Either way, we can tell when we 30493746Sjulian are at the end of the FDE because the symbol becomes defined 30593746Sjulian (in the case of a subtraction, the end symbol, from which the 30693746Sjulian start symbol is being subtracted). Other ways of describing 30793746Sjulian the size will not be optimized. */ 30893746Sjulian if ((exp->X_op == O_symbol || exp->X_op == O_subtract) 30993746Sjulian && ! S_IS_DEFINED (exp->X_add_symbol)) 31093746Sjulian { 31193746Sjulian d->state = state_saw_size; 31293746Sjulian d->size_end_sym = exp->X_add_symbol; 31393746Sjulian } 31493746Sjulian } 31593746Sjulian break; 31693746Sjulian 31793746Sjulian case state_saw_size: 31893746Sjulian case state_saw_cie_offset: 31993746Sjulian /* Assume whatever form it appears in, it appears atomically. */ 32093746Sjulian d->state += 1; 321149151Sjhb break; 32293746Sjulian 323147256Sbrooks case state_saw_pc_begin: 32493746Sjulian /* Decide whether we should see an augmentation. */ 32593746Sjulian if (! d->cie_info_ok 32693746Sjulian && ! (d->cie_info_ok = get_cie_info (&d->cie_info))) 32793746Sjulian d->state = state_error; 32893746Sjulian else if (d->cie_info.z_augmentation) 32993746Sjulian { 33093746Sjulian d->state = state_seeing_aug_size; 33193746Sjulian d->aug_size = 0; 33293746Sjulian d->aug_shift = 0; 33393746Sjulian } 33493746Sjulian else 33593746Sjulian d->state = state_wait_loc4; 33693746Sjulian break; 33793746Sjulian 33893746Sjulian case state_seeing_aug_size: 33993746Sjulian /* Bytes == -1 means this comes from an leb128 directive. */ 340148654Srwatson if ((int)*pnbytes == -1 && exp->X_op == O_constant) 34193746Sjulian { 34293746Sjulian d->aug_size = exp->X_add_number; 34393746Sjulian d->state = state_skipping_aug; 344130270Snaddy } 345130270Snaddy else if (*pnbytes == 1 && exp->X_op == O_constant) 34693746Sjulian { 34793746Sjulian unsigned char byte = exp->X_add_number; 34893746Sjulian d->aug_size |= (byte & 0x7f) << d->aug_shift; 34993746Sjulian d->aug_shift += 7; 35093746Sjulian if ((byte & 0x80) == 0) 35193746Sjulian d->state = state_skipping_aug; 352148654Srwatson } 35393746Sjulian else 35493746Sjulian d->state = state_error; 35593746Sjulian if (d->state == state_skipping_aug && d->aug_size == 0) 35693746Sjulian d->state = state_wait_loc4; 35793746Sjulian break; 35893746Sjulian 35993746Sjulian case state_skipping_aug: 36093746Sjulian if ((int)*pnbytes < 0) 36193746Sjulian d->state = state_error; 36293746Sjulian else 36393746Sjulian { 36493746Sjulian int left = (d->aug_size -= *pnbytes); 36593746Sjulian if (left == 0) 36693746Sjulian d->state = state_wait_loc4; 36793746Sjulian else if (left < 0) 36893746Sjulian d->state = state_error; 36993746Sjulian } 37093746Sjulian break; 37193746Sjulian 372149151Sjhb case state_wait_loc4: 37393746Sjulian if (*pnbytes == 1 37493746Sjulian && exp->X_op == O_constant 37593746Sjulian && exp->X_add_number == DW_CFA_advance_loc4) 37693746Sjulian { 37793746Sjulian /* This might be a DW_CFA_advance_loc4. Record the frag and the 37893746Sjulian position within the frag, so that we can change it later. */ 37993746Sjulian frag_grow (1); 38093746Sjulian d->state = state_saw_loc4; 38193746Sjulian d->loc4_frag = frag_now; 38293746Sjulian d->loc4_fix = frag_now_fix (); 38393746Sjulian } 38493746Sjulian break; 38593746Sjulian 38693746Sjulian case state_saw_loc4: 38793746Sjulian d->state = state_wait_loc4; 38893746Sjulian if (*pnbytes != 4) 38993746Sjulian break; 39093746Sjulian if (exp->X_op == O_constant) 39193746Sjulian { 39293746Sjulian /* This is a case which we can optimize. The two symbols being 39393746Sjulian subtracted were in the same frag and the expression was 39493746Sjulian reduced to a constant. We can do the optimization entirely 39593746Sjulian in this function. */ 39693746Sjulian if (d->cie_info.code_alignment > 0 397149151Sjhb && exp->X_add_number % d->cie_info.code_alignment == 0 39893746Sjulian && exp->X_add_number / d->cie_info.code_alignment < 0x40) 39993746Sjulian { 400147256Sbrooks d->loc4_frag->fr_literal[d->loc4_fix] 40193746Sjulian = DW_CFA_advance_loc 40293746Sjulian | (exp->X_add_number / d->cie_info.code_alignment); 40393746Sjulian /* No more bytes needed. */ 40493746Sjulian return 1; 40593746Sjulian } 40693746Sjulian else if (exp->X_add_number < 0x100) 40793746Sjulian { 40893746Sjulian d->loc4_frag->fr_literal[d->loc4_fix] = DW_CFA_advance_loc1; 40993746Sjulian *pnbytes = 1; 41093746Sjulian } 41193746Sjulian else if (exp->X_add_number < 0x10000) 412162321Sglebius { 413162321Sglebius d->loc4_frag->fr_literal[d->loc4_fix] = DW_CFA_advance_loc2; 41493746Sjulian *pnbytes = 2; 41593746Sjulian } 41693746Sjulian } 41793746Sjulian else if (exp->X_op == O_subtract) 41893746Sjulian { 41993746Sjulian /* This is a case we can optimize. The expression was not 42093746Sjulian reduced, so we can not finish the optimization until the end 42193746Sjulian of the assembly. We set up a variant frag which we handle 42293746Sjulian later. */ 42393746Sjulian int fr_subtype; 42493746Sjulian 42593746Sjulian if (d->cie_info.code_alignment > 0) 42693746Sjulian fr_subtype = d->cie_info.code_alignment << 3; 42793746Sjulian else 42893746Sjulian fr_subtype = 0; 42993746Sjulian 43093746Sjulian frag_var (rs_cfa, 4, 0, fr_subtype, make_expr_symbol (exp), 43193746Sjulian d->loc4_fix, (char *) d->loc4_frag); 43293746Sjulian return 1; 43393746Sjulian } 43493746Sjulian break; 43593746Sjulian 43693746Sjulian case state_error: 43793746Sjulian /* Just skipping everything. */ 43893746Sjulian break; 43993746Sjulian } 44093746Sjulian 44193746Sjulian return 0; 44293746Sjulian} 44393746Sjulian 44493746Sjulian/* The function estimates the size of a rs_cfa variant frag based on 44593746Sjulian the current values of the symbols. It is called before the 44693746Sjulian relaxation loop. We set fr_subtype{0:2} to the expected length. */ 44793746Sjulian 44893746Sjulianint 44993746Sjulianeh_frame_estimate_size_before_relax (fragS *frag) 45093746Sjulian{ 451162321Sglebius offsetT diff; 45293746Sjulian int ca = frag->fr_subtype >> 3; 45393746Sjulian int ret; 45493746Sjulian 45593746Sjulian diff = resolve_symbol_value (frag->fr_symbol); 45693746Sjulian 457162321Sglebius if (ca > 0 && diff % ca == 0 && diff / ca < 0x40) 45893746Sjulian ret = 0; 45993746Sjulian else if (diff < 0x100) 46093746Sjulian ret = 1; 461162321Sglebius else if (diff < 0x10000) 46293746Sjulian ret = 2; 46393746Sjulian else 46493746Sjulian ret = 4; 46593746Sjulian 46693746Sjulian frag->fr_subtype = (frag->fr_subtype & ~7) | ret; 46793746Sjulian 46893746Sjulian return ret; 469162321Sglebius} 47093746Sjulian 47193746Sjulian/* This function relaxes a rs_cfa variant frag based on the current 47293746Sjulian values of the symbols. fr_subtype{0:2} is the current length of 47393746Sjulian the frag. This returns the change in frag length. */ 47493746Sjulian 47593746Sjulianint 47693746Sjulianeh_frame_relax_frag (fragS *frag) 47793746Sjulian{ 47893746Sjulian int oldsize, newsize; 47993746Sjulian 48093746Sjulian oldsize = frag->fr_subtype & 7; 48195673Sphk newsize = eh_frame_estimate_size_before_relax (frag); 48293746Sjulian return newsize - oldsize; 48393746Sjulian} 48493746Sjulian 48593746Sjulian/* This function converts a rs_cfa variant frag into a normal fill 48693746Sjulian frag. This is called after all relaxation has been done. 48793746Sjulian fr_subtype{0:2} will be the desired length of the frag. */ 48893746Sjulian 48993746Sjulianvoid 49093746Sjulianeh_frame_convert_frag (fragS *frag) 49193746Sjulian{ 49293746Sjulian offsetT diff; 49393746Sjulian fragS *loc4_frag; 49495673Sphk int loc4_fix; 49593746Sjulian 49693746Sjulian loc4_frag = (fragS *) frag->fr_opcode; 49793746Sjulian loc4_fix = (int) frag->fr_offset; 49893746Sjulian 49993746Sjulian diff = resolve_symbol_value (frag->fr_symbol); 50093746Sjulian 50193746Sjulian switch (frag->fr_subtype & 7) 50293746Sjulian { 50393746Sjulian case 0: 50493746Sjulian { 50593746Sjulian int ca = frag->fr_subtype >> 3; 50693746Sjulian assert (ca > 0 && diff % ca == 0 && diff / ca < 0x40); 50793746Sjulian loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc | (diff / ca); 50893746Sjulian } 50993746Sjulian break; 51093746Sjulian 51193746Sjulian case 1: 51293746Sjulian assert (diff < 0x100); 51393746Sjulian loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc1; 51493746Sjulian frag->fr_literal[frag->fr_fix] = diff; 51593746Sjulian break; 51693746Sjulian 51793746Sjulian case 2: 51893746Sjulian assert (diff < 0x10000); 51993746Sjulian loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc2; 52093746Sjulian md_number_to_chars (frag->fr_literal + frag->fr_fix, diff, 2); 52193746Sjulian break; 52293746Sjulian 52393746Sjulian default: 52493746Sjulian md_number_to_chars (frag->fr_literal + frag->fr_fix, diff, 4); 52593746Sjulian break; 52693746Sjulian } 52793746Sjulian 52893746Sjulian frag->fr_fix += frag->fr_subtype & 7; 52993746Sjulian frag->fr_type = rs_fill; 53093746Sjulian frag->fr_subtype = 0; 53193746Sjulian frag->fr_offset = 0; 53293746Sjulian} 53393746Sjulian