1/* Main simulator entry points specific to the eBPF. 2 Copyright (C) 2020 Free Software Foundation, Inc. 3 4 This file is part of GDB, the GNU debugger. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 18 19#include <stdlib.h> 20 21#include "sim-main.h" 22#include "sim-options.h" 23#include "libiberty.h" 24#include "bfd.h" 25 26/* Globals. */ 27 28/* String with the name of the section containing the BPF program to 29 run. */ 30static char *bpf_program_section = NULL; 31 32extern uint64_t skb_data_offset; 33 34 35/* Handle BPF-specific options. */ 36 37static SIM_RC bpf_option_handler (SIM_DESC, sim_cpu *, int, char *, int); 38 39typedef enum 40{ 41 OPTION_BPF_SET_PROGRAM = OPTION_START, 42 OPTION_BPF_LIST_PROGRAMS, 43 OPTION_BPF_VERIFY_PROGRAM, 44 OPTION_BPF_SKB_DATA_OFFSET, 45} BPF_OPTION; 46 47static const OPTION bpf_options[] = 48{ 49 { {"bpf-set-program", required_argument, NULL, OPTION_BPF_SET_PROGRAM}, 50 '\0', "SECTION_NAME", "Set the entry point", 51 bpf_option_handler }, 52 { {"bpf-list-programs", no_argument, NULL, OPTION_BPF_LIST_PROGRAMS}, 53 '\0', "", "List loaded bpf programs", 54 bpf_option_handler }, 55 { {"bpf-verify-program", required_argument, NULL, OPTION_BPF_VERIFY_PROGRAM}, 56 '\0', "PROGRAM", "Run the verifier on the given BPF program", 57 bpf_option_handler }, 58 { {"skb-data-offset", required_argument, NULL, OPTION_BPF_SKB_DATA_OFFSET}, 59 '\0', "OFFSET", "Configure offsetof(struct sk_buff, data)", 60 bpf_option_handler }, 61 62 { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL, NULL } 63}; 64 65static SIM_RC 66bpf_option_handler (SIM_DESC sd, sim_cpu *cpu ATTRIBUTE_UNUSED, int opt, 67 char *arg, int is_command ATTRIBUTE_UNUSED) 68{ 69 switch ((BPF_OPTION) opt) 70 { 71 case OPTION_BPF_VERIFY_PROGRAM: 72 /* XXX call the verifier. */ 73 sim_io_printf (sd, "Verifying BPF program %s...\n", arg); 74 break; 75 76 case OPTION_BPF_LIST_PROGRAMS: 77 /* XXX list programs. */ 78 sim_io_printf (sd, "BPF programs available:\n"); 79 break; 80 81 case OPTION_BPF_SET_PROGRAM: 82 /* XXX: check that the section exists and tell the user about a 83 new start_address. */ 84 bpf_program_section = xstrdup (arg); 85 break; 86 87 case OPTION_BPF_SKB_DATA_OFFSET: 88 skb_data_offset = strtoul (arg, NULL, 0); 89 break; 90 91 default: 92 sim_io_eprintf (sd, "Unknown option `%s'\n", arg); 93 return SIM_RC_FAIL; 94 } 95 96 return SIM_RC_OK; 97} 98 99/* Like sim_state_free, but free the cpu buffers as well. */ 100 101static void 102bpf_free_state (SIM_DESC sd) 103{ 104 if (STATE_MODULES (sd) != NULL) 105 sim_module_uninstall (sd); 106 107 sim_cpu_free_all (sd); 108 sim_state_free (sd); 109} 110 111/* Create an instance of the simulator. */ 112 113SIM_DESC 114sim_open (SIM_OPEN_KIND kind, 115 host_callback *callback, 116 struct bfd *abfd, 117 char * const *argv) 118{ 119 /* XXX Analyze the program, and collect per-function information 120 like the kernel verifier does. The implementation of the CALL 121 instruction will need that information, to update %fp. */ 122 123 SIM_DESC sd = sim_state_alloc (kind, callback); 124 125 if (sim_cpu_alloc_all (sd, 1, cgen_cpu_max_extra_bytes ()) 126 != SIM_RC_OK) 127 goto error; 128 129 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK) 130 goto error; 131 132 /* Add the BPF-specific option list to the simulator. */ 133 if (sim_add_option_table (sd, NULL, bpf_options) != SIM_RC_OK) 134 { 135 bpf_free_state (sd); 136 return 0; 137 } 138 139 if (sim_parse_args (sd, argv) != SIM_RC_OK) 140 goto error; 141 142 if (sim_analyze_program (sd, 143 (STATE_PROG_ARGV (sd) != NULL 144 ? *STATE_PROG_ARGV (sd) 145 : NULL), abfd) != SIM_RC_OK) 146 goto error; 147 148 if (sim_config (sd) != SIM_RC_OK) 149 goto error; 150 151 if (sim_post_argv_init (sd) != SIM_RC_OK) 152 goto error; 153 154 /* ... */ 155 156 /* Initialize the CPU descriptors and the disassemble in the cpu 157 descriptor table entries. */ 158 { 159 int i; 160 CGEN_CPU_DESC cd = bpf_cgen_cpu_open_1 (STATE_ARCHITECTURE (sd)->printable_name, 161 CGEN_ENDIAN_LITTLE); 162 163 /* We have one cpu per installed program! MAX_NR_PROCESSORS is an 164 arbitrary upper limit. XXX where is it defined? */ 165 for (i = 0; i < MAX_NR_PROCESSORS; ++i) 166 { 167 SIM_CPU *cpu = STATE_CPU (sd, i); 168 169 CPU_CPU_DESC (cpu) = cd; 170 CPU_DISASSEMBLER (cpu) = sim_cgen_disassemble_insn; 171 } 172 173 bpf_cgen_init_dis (cd); 174 } 175 176 /* Initialize various cgen things not done by common framework. 177 Must be done after bpf_cgen_cpu_open. */ 178 cgen_init (sd); 179 180 /* XXX do eBPF sim specific initializations. */ 181 182 return sd; 183 184 error: 185 bpf_free_state (sd); 186 return NULL; 187} 188 189 190SIM_RC 191sim_create_inferior (SIM_DESC sd, struct bfd *abfd, 192 char *const *argv, char *const *envp) 193{ 194 SIM_CPU *current_cpu = STATE_CPU (sd, 0); 195 SIM_ADDR addr; 196 197 /* Determine the start address. 198 199 XXX acknowledge bpf_program_section. If it is NULL, emit a 200 warning explaining that we are using the ELF file start address, 201 which often is not what is actually wanted. */ 202 if (abfd != NULL) 203 addr = bfd_get_start_address (abfd); 204 else 205 addr = 0; 206 207 sim_pc_set (current_cpu, addr); 208 209 if (STATE_PROG_ARGV (sd) != argv) 210 { 211 freeargv (STATE_PROG_ARGV (sd)); 212 STATE_PROG_ARGV (sd) = dupargv (argv); 213 } 214 215 return SIM_RC_OK; 216} 217