From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from EUR05-AM6-obe.outbound.protection.outlook.com (mail-am6eur05on2041.outbound.protection.outlook.com [40.107.22.41]) by sourceware.org (Postfix) with ESMTPS id 81AA73829BF2 for ; Fri, 10 Jun 2022 13:35:11 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 81AA73829BF2 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=VBvSIaFoYPUWfTlSd9+LHPZdnxcfqLgFPpFvjxsG8WUiWWpIUSIlbuk5bWx/mjmkWlkQtkk8L4TZZA/g+ws0bZO4ypRbIXg4vCrtAeY+3sT+1EjKyMeGOuXNPuDxXMqQiUB4u6kJl9f2q05ZXDUWnFQatbiIoYXG9Pcx3eIIcmIPByW9NsXG4Ynkh1Cdqi0pgQAdk6EpAGPBHuf49fwdbfdO7uO8mSVlc9aF/mNuYN/3a+R2CIS9E9M0pX4N9+whgRvr74ySZvRKnxfMKnYmbNdiMTv4KtMrDv8OIbJZ/1U4HkI2GPyNBtqyXLo/S85YfImhZFsJJLmyCfMUDGjqNw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=763eThc0LZ39hx3CvJguF+u+FiNyGohfCPD9qDwMz4A=; b=PoLRP3KslTpKKHQnfi99403x8Wjy270idW/iTRuQgWtzH0cvRUHzuEzabjYnPrBe1eCqCf750NVSo7PRAX2uaeSce96V+P01OAMWgDWdCfjgdc+5s3Zs+Bxd5Jprz9E0YwqrMXHYbUAKVujedh+mVOPT27id/G5O0M8SZeHBp7VCvh26zy24eb/PhPvz2pjGsKD9hBDoSdoFS+gAbs5MTNfk0PeNnd0RB6y+iKtLVKMPBcJnMk3300LjpW5A33T50nSDHccIVNcXaMJ3vsRapY1gEST2xppkTM80Dl1DrWH4ZCelV6eNy/icNGGx7nCDfNVns7vsWSa+2KhfgSRATA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=suse.com; dmarc=pass action=none header.from=suse.com; dkim=pass header.d=suse.com; arc=none Received: from VE1PR04MB6560.eurprd04.prod.outlook.com (2603:10a6:803:122::25) by PA4PR04MB7806.eurprd04.prod.outlook.com (2603:10a6:102:c9::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5332.14; Fri, 10 Jun 2022 13:35:09 +0000 Received: from VE1PR04MB6560.eurprd04.prod.outlook.com ([fe80::dfa:a64a:432f:e26b]) by VE1PR04MB6560.eurprd04.prod.outlook.com ([fe80::dfa:a64a:432f:e26b%7]) with mapi id 15.20.5332.013; Fri, 10 Jun 2022 13:35:09 +0000 Message-ID: Date: Fri, 10 Jun 2022 15:35:07 +0200 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Thunderbird/91.10.0 Subject: [PATCH 1/4] x86: properly initialize struct instr_info instance(s) Content-Language: en-US To: Binutils References: <6fd28ca0-2af4-7335-18d3-31036dea7a4f@suse.com> From: Jan Beulich In-Reply-To: <6fd28ca0-2af4-7335-18d3-31036dea7a4f@suse.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-ClientProxiedBy: AS9P251CA0020.EURP251.PROD.OUTLOOK.COM (2603:10a6:20b:50f::25) To VE1PR04MB6560.eurprd04.prod.outlook.com (2603:10a6:803:122::25) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 7f987abd-c48b-41c9-05a5-08da4ae6098f X-MS-TrafficTypeDiagnostic: PA4PR04MB7806:EE_ X-Microsoft-Antispam-PRVS: X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: lF+6+BpgjZM/UoTOtdjTz3JqlfHLnUIlValzTiadzCB9YCIVjLmI9W6wlvLt3ZbXdSBHN5TjA0ZU9ejaZkYVMB7EqpQGeMmsVBBMvVs9tXsGlR2+rQxm8sMsyMVKgb3tyMsZ750RNP8hHMcHV1rC47D1K4xJEMZeb9fPtdoeoTYSnp9VvLwEkfIMKjRXG5JOY8/P0tdpcGBL18lWBFw3CaKMVjxbthIm33xhBoEz6s/JyDg8ru/GXC45IAdlF8CE2vGwkhNEdHk0CtXrvFM+bS5ZszbnH2fh3AtJnxXTqUvgoO9Zb5Y0tSvIMRib1biddOEtJxJHjd0BDu824xt/JZtuxzbC/rbDRzaOMkycm0tl/xFXwmJ1/0wcjPlw7/l4rThkg5h8Hlus6muLgSKkaSUekkBaMFx2E8vB4P8GtgA2waTsc6mlYwzbb1TDVlHA7ibhFHgaum4xu8arzqzo7o8GGdB6UmktOP71kW3DBKhl8yNUm6lyS72x8u4GMjvbYKB7ntvyk1v7fD+hRd5mUiasTIyLGadXjK5GrXMYMZyeWEWvzLhMiFSpvimXya3Nw6sDBesQjdZxvwFqX80IcaGJk5XsoIxXueSQD7Lwlg2Z7KiezHEG/9w8/Inb0Ju71W57uRQBuz/jhfb4snCUMW9LwshXy4QwyiOCYumZTFxN4nfXCsZQo77n32lICQcWA0pDuvqc8+BWyumOOjpmwWVARAGhbDHVEg/l5zgFHrWpzX3zXZPikptSGh3pMN3I X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:VE1PR04MB6560.eurprd04.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230001)(366004)(6916009)(38100700002)(186003)(86362001)(54906003)(36756003)(31686004)(2616005)(26005)(30864003)(6512007)(66946007)(66556008)(83380400001)(8936002)(66476007)(4326008)(8676002)(2906002)(316002)(6486002)(6506007)(31696002)(5660300002)(508600001)(43740500002)(45980500001); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?OW9EOVlyckFCbzdXSVVLTkhya0U3RDVBdmk1dWlaZkFjSGo3WEUwckN5QzFu?= =?utf-8?B?T3NlZ0VpQjYzdXFxWGZVM3pTRVo0YUcwYXA5a2hDVFYzTWlGZlEvMTZlTzU5?= =?utf-8?B?cWxsSm5NUG1kaVY3NUFZTk0vWjNVM3dVZTZtbElCT3FNSzNXYkhmdXhvZElq?= =?utf-8?B?aThhR3FtWUJDbE9rZE13SXVGODVBSlRtNnJ0My9zV3MwdnFaU1lOUHhUZmFE?= =?utf-8?B?NGx4aGxkc0xvMXRkYzlndVd2d0FYUUUrckZiQkVwZzh2NDBvVG1OK1ZvLzA0?= =?utf-8?B?TlkvU3ZUSUVkS2I4bzNHVjlCRlQvMmE4VVQrYTNQa0U1U0Z5SktSUG5ONENF?= =?utf-8?B?YVVpbnlHTVlCbVRNb3hXRWtnUkZuVFZuMzYxTFp3SS8zZU1hNWRXSS9ObWx2?= =?utf-8?B?L2QvejB1bktFQnVhWm9UbElFQVJpVjl0b0xkdHBGamVNbDlnTDFZWUJaVnFB?= =?utf-8?B?Y0tBS1VmVVNSMi9tTENJTlBFc0grZHh3M0lEeWU3Z1YyUXBVQUJ4aWZBbE5n?= =?utf-8?B?SDBlQy9STlEycGNrbDB4VkJkMzR1Z3BqdlZkTXMrRFJ0Lzh6Ly9wdXFzRG1i?= =?utf-8?B?dEVoUXVERTlPdCs1NnpKRVU5a2dyMGVCTmdUeWJva2o3VE9WL0p2ZmsvbS9q?= =?utf-8?B?cmoxVnZDbUd4RUZESFllUWlPcXd4L24rdUViOFVjQTdsai9ibVhRV3RLeWZ5?= =?utf-8?B?bGhkU2FnQ043SUF2bmhBRzRYSTJWVEc2d2hzUnRvdVdWRjdMeVdsay9jUTRX?= =?utf-8?B?L2l1anhudEdkV1Y1ek90OGRIdWVrakFwTDNyOHRHSjlnczN0bUtFaVlwWEtn?= =?utf-8?B?Ukd6ZGIzdit5cWNsZTU4UXZMVy84WWo1QlUyQ1dWT0RPSk9qMmN2TFk5aktM?= =?utf-8?B?M3d6M1dGRE5TMFZOWUwzQ09HNTVwUXp6SHFFZUI5NVZKejA3Z2hoMy9vNjBz?= =?utf-8?B?Rzhia0d6MGs1NUVZU3dkQXhPQjgzdUpLVGE3NnVmaE41eEorS1dvd01YN25x?= =?utf-8?B?TzloTWNrT29udU44eTdXM2w0aWJycnhxUUZPVzVlZlFkSzJEMmI1QXZ1RFlP?= =?utf-8?B?eld0VHpFM2VacXBENEV1RXY3NVZxeFllOGlJTnBockc4cnRkQ1FoejA2QUxB?= =?utf-8?B?UXlYZlJZUk9LMTNxd2ZVVFZyNlhsK3NxRGxDTWlRSE9tZTdheENSOHcwNlBD?= =?utf-8?B?TUF5Yk0zaE50dktJYytobVRYeVdnSXg0aytucFZyNlJPbHJoa2hPTnpHblBU?= =?utf-8?B?RGxHRkxUeFNwNkxKdFNaZXRlVzFnTGI1aTkwYVN5Z3NoU0JEemFxWDBOSmRs?= =?utf-8?B?MVo1ZkZQWUJ3MW5mUll0VG9tYTdBamV3WE1YV1dlMFBaamU4RnY4L0pXbnN0?= =?utf-8?B?OVNETERxQ1JjMExQS0gyRTYrc3RNU3RKVmljQlVuMXpWKzV4UktJT3R1U1RQ?= =?utf-8?B?K1cwVWRIbUpEQ2hCSC9GRTRhSFIwc2dtVktkeEVPZWRhekNYNnhNT0laUkFO?= =?utf-8?B?Qk5zcU1WanR5WmpJVEhOZkFuN2VyV3lpUW5aVnY0V3Mvckw4cUh1RTJVcC9a?= =?utf-8?B?akRFanJ6STUwU1pNZ3VHUjFYY3ZBU1FOL0VEVzNqNVhQYVc2cEg3cTVKWHMy?= =?utf-8?B?d01PUVZLZHFQRVd5cFovUDl0ZStQSDhLNlF0SG5lcmNXbHlaamYrMU1ZMnZL?= =?utf-8?B?TXA2WkRkM1lPb05WN0NmSjdyYWh0Y1lsTlFoT0gwN0dJZnNPZFBORG5sSWNG?= =?utf-8?B?WVJBeGFIbnc2SGxqWUVlRm5Rbll2cHJ0S2N1R3lncUI3UngwSkNNRkJyYTJT?= =?utf-8?B?VDF1QTJvL1FOTkoyNDVNbE5WTWhxNEZLd2d5c1BHbW5TV1Bxc1ZIWXNOWGxD?= =?utf-8?B?MzFGdFkrUHVhUGM5eTR4bUt2bG1jNmZja3hkMVZ1VlhESEkrVmNrR2dIWXcz?= =?utf-8?B?SU8rOHplbFd0SzVjelZTZkFWTlN3TU05b2RyKzgwanE0UkxCaEl0dkxsQmVa?= =?utf-8?B?VVFCaHNHQmVLOW5PUnMwSTAvajBmSHJkb2g0RlBiRWFHN24yVmRNVFgxWlRX?= =?utf-8?B?WFNPeTIxbTFoTkY1YkM1dWJSZUtuR2thSndCdjZWK1EyQUhjVGpJZHBNZCt0?= =?utf-8?B?bXRMRlZteUxnUmxDb3BQbU0wR0llSnRZTUVTdUpNL1NYVGJ2Qm12V3ZqODJl?= =?utf-8?B?Mllhc01FL0VMNWJyUHJ4ZjRJWTJUdUMxU2xWQTcvYjNxN1VJbnhpMkxuNWdy?= =?utf-8?B?R1g5ZlZXNmtjdjNtZ3RDRFhLck53RkY4U3Uxek5vRWJUZEJDcTdPUWpJbGdm?= =?utf-8?B?Sm10WHJRNFZYTHNHek9WbWFJSXRid0hHeGxualc0dlhFTHNFUklzUT09?= X-OriginatorOrg: suse.com X-MS-Exchange-CrossTenant-Network-Message-Id: 7f987abd-c48b-41c9-05a5-08da4ae6098f X-MS-Exchange-CrossTenant-AuthSource: VE1PR04MB6560.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 10 Jun 2022 13:35:09.2147 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: f7a17af6-1c5c-4a36-aa8b-f5be247aa4ba X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: NCqB32LeTSYCmE12gWLucRT8RtiSbETFQIXo2+TdrRw70pHzglS4y8Ur0BnMX77nzkI8lmzw6OVpLIip+7+s4w== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PA4PR04MB7806 X-Spam-Status: No, score=-3031.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_PASS, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 10 Jun 2022 13:35:15 -0000 Commit 39fb369834a3 ("opcodes: Make i386-dis.c thread-safe") introduced a lot of uninitialized data. Alan has in particular observed ubsan taking issue with the loop inverting the order of operands, where op_riprel[] - an array of bool - can hold values other than 0 or 1. Move instantiation of struct instr_info into print_insn() (thus having just a single central point), and make use of C99 dedicated initializers to fill fields right in the initializer where possible. This way all fields not explicitly initialized will be zero-filled, which in turn allows dropping of some other explicit initialization later in the function or in ckprefix(). Additionally this removes a lot of indirection, as all "ins->info" uses can simply become "info". Make one further arrangement though, to limit the amount of data needing (zero)initializing on every invocation: Convert the op_out structure member to just an array of pointers, with the actual arrays living inside print_insn() (and, as befoe, having just their 1st char filled with nul). While there, instead of adjusting print_insn()'s forward declaration, arrange for no such declaration to be needed in the first place. --- Since I'm touching quite a few instances of indirect function calls, I was tempted to drop the explicit indirection. With C99 (and even with earlier ANSI C) this shouldn't be needed and imo makes the code harder to read. But then I hesitated since maybe someone really wants this written this way? --- a/opcodes/i386-dis.c +++ b/opcodes/i386-dis.c @@ -42,7 +42,6 @@ #include typedef struct instr_info instr_info; -static int print_insn (bfd_vma, instr_info *); static void dofloat (instr_info *, int); static void OP_ST (instr_info *, int, int); static void OP_STi (instr_info *, int, int); @@ -234,7 +233,7 @@ struct instr_info unsigned char op_ad; signed char op_index[MAX_OPERANDS]; bool op_riprel[MAX_OPERANDS]; - char op_out[MAX_OPERANDS][100]; + char *op_out[MAX_OPERANDS]; bfd_vma op_address[MAX_OPERANDS]; bfd_vma start_pc; @@ -8545,22 +8544,7 @@ static int ckprefix (instr_info *ins) { int newrex, i, length; - ins->rex = 0; - ins->prefixes = 0; - ins->used_prefixes = 0; - ins->rex_used = 0; - ins->evex_used = 0; - ins->last_lock_prefix = -1; - ins->last_repz_prefix = -1; - ins->last_repnz_prefix = -1; - ins->last_data_prefix = -1; - ins->last_addr_prefix = -1; - ins->last_rex_prefix = -1; - ins->last_seg_prefix = -1; - ins->fwait_prefix = -1; - ins->active_seg_prefix = 0; - for (i = 0; i < (int) ARRAY_SIZE (ins->all_prefixes); i++) - ins->all_prefixes[i] = 0; + i = 0; length = 0; /* The maximum instruction length is 15bytes. */ @@ -8769,39 +8753,6 @@ prefix_name (instr_info *ins, int pref, } } -/* Here for backwards compatibility. When gdb stops using - print_insn_i386_att and print_insn_i386_intel these functions can - disappear, and print_insn_i386 be merged into print_insn. */ -int -print_insn_i386_att (bfd_vma pc, disassemble_info *info) -{ - instr_info ins; - ins.info = info; - ins.intel_syntax = 0; - - return print_insn (pc, &ins); -} - -int -print_insn_i386_intel (bfd_vma pc, disassemble_info *info) -{ - instr_info ins; - ins.info = info; - ins.intel_syntax = 1; - - return print_insn (pc, &ins); -} - -int -print_insn_i386 (bfd_vma pc, disassemble_info *info) -{ - instr_info ins; - ins.info = info; - ins.intel_syntax = -1; - - return print_insn (pc, &ins); -} - void print_i386_disassembler_options (FILE *stream) { @@ -9421,7 +9372,7 @@ i386_dis_printf (instr_info *ins, enum d } static int -print_insn (bfd_vma pc, instr_info *ins) +print_insn (bfd_vma pc, disassemble_info *info, int intel_syntax) { const struct dis386 *dp; int i; @@ -9433,60 +9384,75 @@ print_insn (bfd_vma pc, instr_info *ins) struct dis_private priv; int prefix_length; int op_count; + instr_info ins = { + .info = info, + .intel_syntax = intel_syntax >= 0 + ? intel_syntax + : (info->mach & bfd_mach_i386_intel_syntax) != 0, + .intel_mnemonic = !SYSV386_COMPAT, + .op_index[0 ... MAX_OPERANDS - 1] = -1, + .start_pc = pc, + .start_codep = priv.the_buffer, + .codep = priv.the_buffer, + .obufp = ins.obuf, + .last_lock_prefix = -1, + .last_repz_prefix = -1, + .last_repnz_prefix = -1, + .last_data_prefix = -1, + .last_addr_prefix = -1, + .last_rex_prefix = -1, + .last_seg_prefix = -1, + .fwait_prefix = -1, + }; + char op_out[MAX_OPERANDS][100]; - ins->isa64 = 0; - ins->intel_mnemonic = !SYSV386_COMPAT; - ins->op_is_jump = false; priv.orig_sizeflag = AFLAG | DFLAG; - if ((ins->info->mach & bfd_mach_i386_i386) != 0) - ins->address_mode = mode_32bit; - else if (ins->info->mach == bfd_mach_i386_i8086) + if ((info->mach & bfd_mach_i386_i386) != 0) + ins.address_mode = mode_32bit; + else if (info->mach == bfd_mach_i386_i8086) { - ins->address_mode = mode_16bit; + ins.address_mode = mode_16bit; priv.orig_sizeflag = 0; } else - ins->address_mode = mode_64bit; - - if (ins->intel_syntax == (char) -1) - ins->intel_syntax = (ins->info->mach & bfd_mach_i386_intel_syntax) != 0; + ins.address_mode = mode_64bit; - for (p = ins->info->disassembler_options; p != NULL;) + for (p = info->disassembler_options; p != NULL;) { if (startswith (p, "amd64")) - ins->isa64 = amd64; + ins.isa64 = amd64; else if (startswith (p, "intel64")) - ins->isa64 = intel64; + ins.isa64 = intel64; else if (startswith (p, "x86-64")) { - ins->address_mode = mode_64bit; + ins.address_mode = mode_64bit; priv.orig_sizeflag |= AFLAG | DFLAG; } else if (startswith (p, "i386")) { - ins->address_mode = mode_32bit; + ins.address_mode = mode_32bit; priv.orig_sizeflag |= AFLAG | DFLAG; } else if (startswith (p, "i8086")) { - ins->address_mode = mode_16bit; + ins.address_mode = mode_16bit; priv.orig_sizeflag &= ~(AFLAG | DFLAG); } else if (startswith (p, "intel")) { - ins->intel_syntax = 1; + ins.intel_syntax = 1; if (startswith (p + 5, "-mnemonic")) - ins->intel_mnemonic = true; + ins.intel_mnemonic = true; } else if (startswith (p, "att")) { - ins->intel_syntax = 0; + ins.intel_syntax = 0; if (startswith (p + 3, "-mnemonic")) - ins->intel_mnemonic = false; + ins.intel_mnemonic = false; } else if (startswith (p, "addr")) { - if (ins->address_mode == mode_64bit) + if (ins.address_mode == mode_64bit) { if (p[4] == '3' && p[5] == '2') priv.orig_sizeflag &= ~AFLAG; @@ -9516,46 +9482,41 @@ print_insn (bfd_vma pc, instr_info *ins) p++; } - if (ins->address_mode == mode_64bit && sizeof (bfd_vma) < 8) + if (ins.address_mode == mode_64bit && sizeof (bfd_vma) < 8) { - i386_dis_printf (ins, dis_style_text, _("64-bit address is disabled")); + i386_dis_printf (&ins, dis_style_text, _("64-bit address is disabled")); return -1; } - if (ins->intel_syntax) + if (ins.intel_syntax) { - ins->open_char = '['; - ins->close_char = ']'; - ins->separator_char = '+'; - ins->scale_char = '*'; + ins.open_char = '['; + ins.close_char = ']'; + ins.separator_char = '+'; + ins.scale_char = '*'; } else { - ins->open_char = '('; - ins->close_char = ')'; - ins->separator_char = ','; - ins->scale_char = ','; + ins.open_char = '('; + ins.close_char = ')'; + ins.separator_char = ','; + ins.scale_char = ','; } /* The output looks better if we put 7 bytes on a line, since that puts most long word instructions on a single line. */ - ins->info->bytes_per_line = 7; + info->bytes_per_line = 7; - ins->info->private_data = &priv; + info->private_data = &priv; priv.max_fetched = priv.the_buffer; priv.insn_start = pc; - ins->obuf[0] = 0; for (i = 0; i < MAX_OPERANDS; ++i) { - ins->op_out[i][0] = 0; - ins->op_index[i] = -1; + op_out[i][0] = 0; + ins.op_out[i] = op_out[i]; } - ins->start_pc = pc; - ins->start_codep = priv.the_buffer; - ins->codep = priv.the_buffer; - if (OPCODES_SIGSETJMP (priv.bailout) != 0) { const char *name; @@ -9563,17 +9524,17 @@ print_insn (bfd_vma pc, instr_info *ins) /* Getting here means we tried for data but didn't get it. That means we have an incomplete instruction of some sort. Just print the first byte as a prefix or a .byte pseudo-op. */ - if (ins->codep > priv.the_buffer) + if (ins.codep > priv.the_buffer) { - name = prefix_name (ins, priv.the_buffer[0], priv.orig_sizeflag); + name = prefix_name (&ins, priv.the_buffer[0], priv.orig_sizeflag); if (name != NULL) - i386_dis_printf (ins, dis_style_mnemonic, "%s", name); + i386_dis_printf (&ins, dis_style_mnemonic, "%s", name); else { /* Just print the first byte as a .byte instruction. */ - i386_dis_printf (ins, dis_style_assembler_directive, + i386_dis_printf (&ins, dis_style_assembler_directive, ".byte "); - i386_dis_printf (ins, dis_style_immediate, "0x%x", + i386_dis_printf (&ins, dis_style_immediate, "0x%x", (unsigned int) priv.the_buffer[0]); } @@ -9583,134 +9544,129 @@ print_insn (bfd_vma pc, instr_info *ins) return -1; } - ins->obufp = ins->obuf; sizeflag = priv.orig_sizeflag; - if (!ckprefix (ins) || ins->rex_used) + if (!ckprefix (&ins) || ins.rex_used) { - /* Too many ins->prefixes or unused REX ins->prefixes. */ + /* Too many prefixes or unused REX prefixes. */ for (i = 0; - i < (int) ARRAY_SIZE (ins->all_prefixes) && ins->all_prefixes[i]; + i < (int) ARRAY_SIZE (ins.all_prefixes) && ins.all_prefixes[i]; i++) - i386_dis_printf (ins, dis_style_mnemonic, "%s%s", + i386_dis_printf (&ins, dis_style_mnemonic, "%s%s", (i == 0 ? "" : " "), - prefix_name (ins, ins->all_prefixes[i], sizeflag)); + prefix_name (&ins, ins.all_prefixes[i], sizeflag)); return i; } - ins->insn_codep = ins->codep; + ins.insn_codep = ins.codep; - FETCH_DATA (ins->info, ins->codep + 1); - ins->two_source_ops = (*ins->codep == 0x62) || (*ins->codep == 0xc8); + FETCH_DATA (info, ins.codep + 1); + ins.two_source_ops = (*ins.codep == 0x62) || (*ins.codep == 0xc8); - if (((ins->prefixes & PREFIX_FWAIT) - && ((*ins->codep < 0xd8) || (*ins->codep > 0xdf)))) + if (((ins.prefixes & PREFIX_FWAIT) + && ((*ins.codep < 0xd8) || (*ins.codep > 0xdf)))) { - /* Handle ins->prefixes before fwait. */ - for (i = 0; i < ins->fwait_prefix && ins->all_prefixes[i]; + /* Handle ins.prefixes before fwait. */ + for (i = 0; i < ins.fwait_prefix && ins.all_prefixes[i]; i++) - i386_dis_printf (ins, dis_style_mnemonic, "%s ", - prefix_name (ins, ins->all_prefixes[i], sizeflag)); - i386_dis_printf (ins, dis_style_mnemonic, "fwait"); + i386_dis_printf (&ins, dis_style_mnemonic, "%s ", + prefix_name (&ins, ins.all_prefixes[i], sizeflag)); + i386_dis_printf (&ins, dis_style_mnemonic, "fwait"); return i + 1; } - if (*ins->codep == 0x0f) + if (*ins.codep == 0x0f) { unsigned char threebyte; - ins->codep++; - FETCH_DATA (ins->info, ins->codep + 1); - threebyte = *ins->codep; + ins.codep++; + FETCH_DATA (info, ins.codep + 1); + threebyte = *ins.codep; dp = &dis386_twobyte[threebyte]; - ins->need_modrm = twobyte_has_modrm[threebyte]; - ins->codep++; + ins.need_modrm = twobyte_has_modrm[threebyte]; + ins.codep++; } else { - dp = &dis386[*ins->codep]; - ins->need_modrm = onebyte_has_modrm[*ins->codep]; - ins->codep++; + dp = &dis386[*ins.codep]; + ins.need_modrm = onebyte_has_modrm[*ins.codep]; + ins.codep++; } - /* Save sizeflag for printing the extra ins->prefixes later before updating + /* Save sizeflag for printing the extra ins.prefixes later before updating it for mnemonic and operand processing. The prefix names depend only on the address mode. */ orig_sizeflag = sizeflag; - if (ins->prefixes & PREFIX_ADDR) + if (ins.prefixes & PREFIX_ADDR) sizeflag ^= AFLAG; - if ((ins->prefixes & PREFIX_DATA)) + if ((ins.prefixes & PREFIX_DATA)) sizeflag ^= DFLAG; - ins->end_codep = ins->codep; - if (ins->need_modrm) + ins.end_codep = ins.codep; + if (ins.need_modrm) { - FETCH_DATA (ins->info, ins->codep + 1); - ins->modrm.mod = (*ins->codep >> 6) & 3; - ins->modrm.reg = (*ins->codep >> 3) & 7; - ins->modrm.rm = *ins->codep & 7; + FETCH_DATA (info, ins.codep + 1); + ins.modrm.mod = (*ins.codep >> 6) & 3; + ins.modrm.reg = (*ins.codep >> 3) & 7; + ins.modrm.rm = *ins.codep & 7; } - else - memset (&ins->modrm, 0, sizeof (ins->modrm)); - - ins->need_vex = false; - memset (&ins->vex, 0, sizeof (ins->vex)); if (dp->name == NULL && dp->op[0].bytemode == FLOATCODE) { - get_sib (ins, sizeflag); - dofloat (ins, sizeflag); + get_sib (&ins, sizeflag); + dofloat (&ins, sizeflag); } else { - dp = get_valid_dis386 (dp, ins); - if (dp != NULL && putop (ins, dp->name, sizeflag) == 0) + dp = get_valid_dis386 (dp, &ins); + if (dp != NULL && putop (&ins, dp->name, sizeflag) == 0) { - get_sib (ins, sizeflag); + get_sib (&ins, sizeflag); for (i = 0; i < MAX_OPERANDS; ++i) { - ins->obufp = ins->op_out[i]; - ins->op_ad = MAX_OPERANDS - 1 - i; + ins.obufp = ins.op_out[i]; + ins.op_ad = MAX_OPERANDS - 1 - i; if (dp->op[i].rtn) - (*dp->op[i].rtn) (ins, dp->op[i].bytemode, sizeflag); + (*dp->op[i].rtn) (&ins, dp->op[i].bytemode, sizeflag); /* For EVEX instruction after the last operand masking should be printed. */ - if (i == 0 && ins->vex.evex) + if (i == 0 && ins.vex.evex) { /* Don't print {%k0}. */ - if (ins->vex.mask_register_specifier) + if (ins.vex.mask_register_specifier) { const char *reg_name - = att_names_mask[ins->vex.mask_register_specifier]; - oappend (ins, "{"); - oappend_register (ins, reg_name); - oappend (ins, "}"); + = att_names_mask[ins.vex.mask_register_specifier]; + + oappend (&ins, "{"); + oappend_register (&ins, reg_name); + oappend (&ins, "}"); } - if (ins->vex.zeroing) - oappend (ins, "{z}"); + if (ins.vex.zeroing) + oappend (&ins, "{z}"); /* S/G insns require a mask and don't allow zeroing-masking. */ if ((dp->op[0].bytemode == vex_vsib_d_w_dq_mode || dp->op[0].bytemode == vex_vsib_q_w_dq_mode) - && (ins->vex.mask_register_specifier == 0 - || ins->vex.zeroing)) - oappend (ins, "/(bad)"); + && (ins.vex.mask_register_specifier == 0 + || ins.vex.zeroing)) + oappend (&ins, "/(bad)"); } } /* Check whether rounding control was enabled for an insn not supporting it. */ - if (ins->modrm.mod == 3 && ins->vex.b - && !(ins->evex_used & EVEX_b_used)) + if (ins.modrm.mod == 3 && ins.vex.b + && !(ins.evex_used & EVEX_b_used)) { for (i = 0; i < MAX_OPERANDS; ++i) { - ins->obufp = ins->op_out[i]; - if (*ins->obufp) + ins.obufp = ins.op_out[i]; + if (*ins.obufp) continue; - oappend (ins, names_rounding[ins->vex.ll]); - oappend (ins, "bad}"); + oappend (&ins, names_rounding[ins.vex.ll]); + oappend (&ins, "bad}"); break; } } @@ -9718,15 +9674,15 @@ print_insn (bfd_vma pc, instr_info *ins) } /* Clear instruction information. */ - ins->info->insn_info_valid = 0; - ins->info->branch_delay_insns = 0; - ins->info->data_size = 0; - ins->info->insn_type = dis_noninsn; - ins->info->target = 0; - ins->info->target2 = 0; + info->insn_info_valid = 0; + info->branch_delay_insns = 0; + info->data_size = 0; + info->insn_type = dis_noninsn; + info->target = 0; + info->target2 = 0; /* Reset jump operation indicator. */ - ins->op_is_jump = false; + ins.op_is_jump = false; { int jump_detection = 0; @@ -9747,28 +9703,28 @@ print_insn (bfd_vma pc, instr_info *ins) /* Determine if this is a jump or branch. */ if ((jump_detection & 0x3) == 0x3) { - ins->op_is_jump = true; + ins.op_is_jump = true; if (jump_detection & 0x4) - ins->info->insn_type = dis_condbranch; + info->insn_type = dis_condbranch; else - ins->info->insn_type = (dp->name && !strncmp (dp->name, "call", 4)) + info->insn_type = (dp->name && !strncmp (dp->name, "call", 4)) ? dis_jsr : dis_branch; } } /* If VEX.vvvv and EVEX.vvvv are unused, they must be all 1s, which are all 0s in inverted form. */ - if (ins->need_vex && ins->vex.register_specifier != 0) + if (ins.need_vex && ins.vex.register_specifier != 0) { - i386_dis_printf (ins, dis_style_text, "(bad)"); - return ins->end_codep - priv.the_buffer; + i386_dis_printf (&ins, dis_style_text, "(bad)"); + return ins.end_codep - priv.the_buffer; } /* If EVEX.z is set, there must be an actual mask register in use. */ - if (ins->vex.zeroing && ins->vex.mask_register_specifier == 0) + if (ins.vex.zeroing && ins.vex.mask_register_specifier == 0) { - i386_dis_printf (ins, dis_style_text, "(bad)"); - return ins->end_codep - priv.the_buffer; + i386_dis_printf (&ins, dis_style_text, "(bad)"); + return ins.end_codep - priv.the_buffer; } switch (dp->prefix_requirement) @@ -9776,12 +9732,12 @@ print_insn (bfd_vma pc, instr_info *ins) case PREFIX_DATA: /* If only the data prefix is marked as mandatory, its absence renders the encoding invalid. Most other PREFIX_OPCODE rules still apply. */ - if (ins->need_vex ? !ins->vex.prefix : !(ins->prefixes & PREFIX_DATA)) + if (ins.need_vex ? !ins.vex.prefix : !(ins.prefixes & PREFIX_DATA)) { - i386_dis_printf (ins, dis_style_text, "(bad)"); - return ins->end_codep - priv.the_buffer; + i386_dis_printf (&ins, dis_style_text, "(bad)"); + return ins.end_codep - priv.the_buffer; } - ins->used_prefixes |= PREFIX_DATA; + ins.used_prefixes |= PREFIX_DATA; /* Fall through. */ case PREFIX_OPCODE: /* If the mandatory PREFIX_REPZ/PREFIX_REPNZ/PREFIX_DATA prefix is @@ -9789,79 +9745,79 @@ print_insn (bfd_vma pc, instr_info *ins) used by putop and MMX/SSE operand and may be overridden by the PREFIX_REPZ/PREFIX_REPNZ fix, we check the PREFIX_DATA prefix separately. */ - if (((ins->need_vex - ? ins->vex.prefix == REPE_PREFIX_OPCODE - || ins->vex.prefix == REPNE_PREFIX_OPCODE - : (ins->prefixes + if (((ins.need_vex + ? ins.vex.prefix == REPE_PREFIX_OPCODE + || ins.vex.prefix == REPNE_PREFIX_OPCODE + : (ins.prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) != 0) - && (ins->used_prefixes + && (ins.used_prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) == 0) - || (((ins->need_vex - ? ins->vex.prefix == DATA_PREFIX_OPCODE - : ((ins->prefixes + || (((ins.need_vex + ? ins.vex.prefix == DATA_PREFIX_OPCODE + : ((ins.prefixes & (PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA)) == PREFIX_DATA)) - && (ins->used_prefixes & PREFIX_DATA) == 0)) - || (ins->vex.evex && dp->prefix_requirement != PREFIX_DATA - && !ins->vex.w != !(ins->used_prefixes & PREFIX_DATA))) + && (ins.used_prefixes & PREFIX_DATA) == 0)) + || (ins.vex.evex && dp->prefix_requirement != PREFIX_DATA + && !ins.vex.w != !(ins.used_prefixes & PREFIX_DATA))) { - i386_dis_printf (ins, dis_style_text, "(bad)"); - return ins->end_codep - priv.the_buffer; + i386_dis_printf (&ins, dis_style_text, "(bad)"); + return ins.end_codep - priv.the_buffer; } break; case PREFIX_IGNORED: /* Zap data size and rep prefixes from used_prefixes and reinstate their origins in all_prefixes. */ - ins->used_prefixes &= ~PREFIX_OPCODE; - if (ins->last_data_prefix >= 0) - ins->all_prefixes[ins->last_data_prefix] = 0x66; - if (ins->last_repz_prefix >= 0) - ins->all_prefixes[ins->last_repz_prefix] = 0xf3; - if (ins->last_repnz_prefix >= 0) - ins->all_prefixes[ins->last_repnz_prefix] = 0xf2; + ins.used_prefixes &= ~PREFIX_OPCODE; + if (ins.last_data_prefix >= 0) + ins.all_prefixes[ins.last_data_prefix] = 0x66; + if (ins.last_repz_prefix >= 0) + ins.all_prefixes[ins.last_repz_prefix] = 0xf3; + if (ins.last_repnz_prefix >= 0) + ins.all_prefixes[ins.last_repnz_prefix] = 0xf2; break; } /* Check if the REX prefix is used. */ - if ((ins->rex ^ ins->rex_used) == 0 - && !ins->need_vex && ins->last_rex_prefix >= 0) - ins->all_prefixes[ins->last_rex_prefix] = 0; + if ((ins.rex ^ ins.rex_used) == 0 + && !ins.need_vex && ins.last_rex_prefix >= 0) + ins.all_prefixes[ins.last_rex_prefix] = 0; /* Check if the SEG prefix is used. */ - if ((ins->prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS | PREFIX_ES - | PREFIX_FS | PREFIX_GS)) != 0 - && (ins->used_prefixes & ins->active_seg_prefix) != 0) - ins->all_prefixes[ins->last_seg_prefix] = 0; + if ((ins.prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS | PREFIX_ES + | PREFIX_FS | PREFIX_GS)) != 0 + && (ins.used_prefixes & ins.active_seg_prefix) != 0) + ins.all_prefixes[ins.last_seg_prefix] = 0; /* Check if the ADDR prefix is used. */ - if ((ins->prefixes & PREFIX_ADDR) != 0 - && (ins->used_prefixes & PREFIX_ADDR) != 0) - ins->all_prefixes[ins->last_addr_prefix] = 0; + if ((ins.prefixes & PREFIX_ADDR) != 0 + && (ins.used_prefixes & PREFIX_ADDR) != 0) + ins.all_prefixes[ins.last_addr_prefix] = 0; /* Check if the DATA prefix is used. */ - if ((ins->prefixes & PREFIX_DATA) != 0 - && (ins->used_prefixes & PREFIX_DATA) != 0 - && !ins->need_vex) - ins->all_prefixes[ins->last_data_prefix] = 0; + if ((ins.prefixes & PREFIX_DATA) != 0 + && (ins.used_prefixes & PREFIX_DATA) != 0 + && !ins.need_vex) + ins.all_prefixes[ins.last_data_prefix] = 0; - /* Print the extra ins->prefixes. */ + /* Print the extra ins.prefixes. */ prefix_length = 0; - for (i = 0; i < (int) ARRAY_SIZE (ins->all_prefixes); i++) - if (ins->all_prefixes[i]) + for (i = 0; i < (int) ARRAY_SIZE (ins.all_prefixes); i++) + if (ins.all_prefixes[i]) { const char *name; - name = prefix_name (ins, ins->all_prefixes[i], orig_sizeflag); + name = prefix_name (&ins, ins.all_prefixes[i], orig_sizeflag); if (name == NULL) abort (); prefix_length += strlen (name) + 1; - i386_dis_printf (ins, dis_style_mnemonic, "%s ", name); + i386_dis_printf (&ins, dis_style_mnemonic, "%s ", name); } /* Check maximum code length. */ - if ((ins->codep - ins->start_codep) > MAX_CODE_LENGTH) + if ((ins.codep - ins.start_codep) > MAX_CODE_LENGTH) { - i386_dis_printf (ins, dis_style_text, "(bad)"); + i386_dis_printf (&ins, dis_style_text, "(bad)"); return MAX_CODE_LENGTH; } @@ -9872,10 +9828,10 @@ print_insn (bfd_vma pc, instr_info *ins) ++op_count; /* Calculate the number of spaces to print after the mnemonic. */ - ins->obufp = ins->mnemonicendp; + ins.obufp = ins.mnemonicendp; if (op_count > 0) { - i = strlen (ins->obuf) + prefix_length; + i = strlen (ins.obuf) + prefix_length; if (i < 7) i = 7 - i; else @@ -9885,21 +9841,21 @@ print_insn (bfd_vma pc, instr_info *ins) i = 0; /* Print the instruction mnemonic along with any trailing whitespace. */ - i386_dis_printf (ins, dis_style_mnemonic, "%s%*s", ins->obuf, i, ""); + i386_dis_printf (&ins, dis_style_mnemonic, "%s%*s", ins.obuf, i, ""); /* The enter and bound instructions are printed with operands in the same order as the intel book; everything else is printed in reverse order. */ intel_swap_2_3 = false; - if (ins->intel_syntax || ins->two_source_ops) + if (ins.intel_syntax || ins.two_source_ops) { for (i = 0; i < MAX_OPERANDS; ++i) - op_txt[i] = ins->op_out[i]; + op_txt[i] = ins.op_out[i]; - if (ins->intel_syntax && dp && dp->op[2].rtn == OP_Rounding + if (ins.intel_syntax && dp && dp->op[2].rtn == OP_Rounding && dp->op[3].rtn == OP_E && dp->op[4].rtn == NULL) { - op_txt[2] = ins->op_out[3]; - op_txt[3] = ins->op_out[2]; + op_txt[2] = ins.op_out[3]; + op_txt[3] = ins.op_out[2]; intel_swap_2_3 = true; } @@ -9907,18 +9863,18 @@ print_insn (bfd_vma pc, instr_info *ins) { bool riprel; - ins->op_ad = ins->op_index[i]; - ins->op_index[i] = ins->op_index[MAX_OPERANDS - 1 - i]; - ins->op_index[MAX_OPERANDS - 1 - i] = ins->op_ad; - riprel = ins->op_riprel[i]; - ins->op_riprel[i] = ins->op_riprel[MAX_OPERANDS - 1 - i]; - ins->op_riprel[MAX_OPERANDS - 1 - i] = riprel; + ins.op_ad = ins.op_index[i]; + ins.op_index[i] = ins.op_index[MAX_OPERANDS - 1 - i]; + ins.op_index[MAX_OPERANDS - 1 - i] = ins.op_ad; + riprel = ins.op_riprel[i]; + ins.op_riprel[i] = ins.op_riprel[MAX_OPERANDS - 1 - i]; + ins.op_riprel[MAX_OPERANDS - 1 - i] = riprel; } } else { for (i = 0; i < MAX_OPERANDS; ++i) - op_txt[MAX_OPERANDS - 1 - i] = ins->op_out[i]; + op_txt[MAX_OPERANDS - 1 - i] = ins.op_out[i]; } needcomma = 0; @@ -9928,7 +9884,7 @@ print_insn (bfd_vma pc, instr_info *ins) /* In Intel syntax embedded rounding / SAE are not separate operands. Instead they're attached to the prior register operand. Simply suppress emission of the comma to achieve that effect. */ - switch (i & -(ins->intel_syntax && dp)) + switch (i & -(ins.intel_syntax && dp)) { case 2: if (dp->op[2].rtn == OP_Rounding && !intel_swap_2_3) @@ -9940,36 +9896,58 @@ print_insn (bfd_vma pc, instr_info *ins) break; } if (needcomma) - i386_dis_printf (ins, dis_style_text, ","); - if (ins->op_index[i] != -1 && !ins->op_riprel[i]) + i386_dis_printf (&ins, dis_style_text, ","); + if (ins.op_index[i] != -1 && !ins.op_riprel[i]) { - bfd_vma target = (bfd_vma) ins->op_address[ins->op_index[i]]; + bfd_vma target = (bfd_vma) ins.op_address[ins.op_index[i]]; - if (ins->op_is_jump) + if (ins.op_is_jump) { - ins->info->insn_info_valid = 1; - ins->info->branch_delay_insns = 0; - ins->info->data_size = 0; - ins->info->target = target; - ins->info->target2 = 0; + info->insn_info_valid = 1; + info->branch_delay_insns = 0; + info->data_size = 0; + info->target = target; + info->target2 = 0; } - (*ins->info->print_address_func) (target, ins->info); + (*info->print_address_func) (target, info); } else - i386_dis_printf (ins, dis_style_text, "%s", op_txt[i]); + i386_dis_printf (&ins, dis_style_text, "%s", op_txt[i]); needcomma = 1; } for (i = 0; i < MAX_OPERANDS; i++) - if (ins->op_index[i] != -1 && ins->op_riprel[i]) + if (ins.op_index[i] != -1 && ins.op_riprel[i]) { - i386_dis_printf (ins, dis_style_comment_start, " # "); - (*ins->info->print_address_func) ((bfd_vma) - (ins->start_pc + (ins->codep - ins->start_codep) - + ins->op_address[ins->op_index[i]]), ins->info); + i386_dis_printf (&ins, dis_style_comment_start, " # "); + (*info->print_address_func) + ((bfd_vma)(ins.start_pc + (ins.codep - ins.start_codep) + + ins.op_address[ins.op_index[i]]), + info); break; } - return ins->codep - priv.the_buffer; + return ins.codep - priv.the_buffer; +} + +/* Here for backwards compatibility. When gdb stops using + print_insn_i386_att and print_insn_i386_intel these functions can + disappear, and print_insn_i386 be merged into print_insn. */ +int +print_insn_i386_att (bfd_vma pc, disassemble_info *info) +{ + return print_insn (pc, info, 0); +} + +int +print_insn_i386_intel (bfd_vma pc, disassemble_info *info) +{ + return print_insn (pc, info, 1); +} + +int +print_insn_i386 (bfd_vma pc, disassemble_info *info) +{ + return print_insn (pc, info, -1); } static const char *float_mem[] = {