-f::
 --fields::
         Comma separated list of fields to print. Options are:
-        comm, tid, pid, time, cpu, event, trace, sym. Field
+        comm, tid, pid, time, cpu, event, trace, ip, sym. Field
         list can be prepended with the type, trace, sw or hw,
         to indicate to which event type the field list applies.
-        e.g., -f sw:comm,tid,time,sym  and -f trace:time,cpu,trace
+        e.g., -f sw:comm,tid,time,ip,sym  and -f trace:time,cpu,trace
 
                perf script -f <fields>
 
        The arguments are processed in the order received. A later usage can
        reset a prior request. e.g.:
     
-               -f trace: -f comm,tid,time,sym
+               -f trace: -f comm,tid,time,ip,sym
     
        The first -f suppresses trace events (field list is ""), but then the
-       second invocation sets the fields to comm,tid,time,sym. In this case a
+       second invocation sets the fields to comm,tid,time,ip,sym. In this case a
        warning is given to the user:
     
                "Overriding previous field request for all events."
     
        Alternativey, consider the order:
     
-               -f comm,tid,time,sym -f trace:
+               -f comm,tid,time,ip,sym -f trace:
     
        The first -f sets the fields for all events and the second -f
        suppresses trace events. The user is given a warning message about
 
        PERF_OUTPUT_CPU             = 1U << 4,
        PERF_OUTPUT_EVNAME          = 1U << 5,
        PERF_OUTPUT_TRACE           = 1U << 6,
-       PERF_OUTPUT_SYM             = 1U << 7,
+       PERF_OUTPUT_IP              = 1U << 7,
+       PERF_OUTPUT_SYM             = 1U << 8,
 };
 
 struct output_option {
        {.str = "cpu",   .field = PERF_OUTPUT_CPU},
        {.str = "event", .field = PERF_OUTPUT_EVNAME},
        {.str = "trace", .field = PERF_OUTPUT_TRACE},
+       {.str = "ip",    .field = PERF_OUTPUT_IP},
        {.str = "sym",   .field = PERF_OUTPUT_SYM},
 };
 
 
                .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
                              PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
-                             PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM,
+                             PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
+                                 PERF_OUTPUT_SYM,
 
                .invalid_fields = PERF_OUTPUT_TRACE,
        },
 
                .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
                              PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
-                             PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM,
+                             PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
+                                 PERF_OUTPUT_SYM,
 
                .invalid_fields = PERF_OUTPUT_TRACE,
        },
 
                .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
                              PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
-                             PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM,
+                             PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
+                                 PERF_OUTPUT_SYM,
 
                .invalid_fields = PERF_OUTPUT_TRACE,
        },
                !perf_session__has_traces(session, "record -R"))
                return -EINVAL;
 
-       if (PRINT_FIELD(SYM)) {
+       if (PRINT_FIELD(IP)) {
                if (perf_event_attr__check_stype(attr, PERF_SAMPLE_IP, "IP",
-                                          PERF_OUTPUT_SYM))
+                                          PERF_OUTPUT_IP))
                        return -EINVAL;
 
                if (!no_callchain &&
                    !(attr->sample_type & PERF_SAMPLE_CALLCHAIN))
                        symbol_conf.use_callchain = false;
        }
+       if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP)) {
+               pr_err("Display of symbols requested but IP is not selected.\n"
+                      "No addresses to convert to symbols.\n");
+               return -EINVAL;
+       }
 
        if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) &&
                perf_event_attr__check_stype(attr, PERF_SAMPLE_TID, "TID",
        if (PRINT_FIELD(COMM)) {
                if (latency_format)
                        printf("%8.8s ", thread->comm);
-               else if (PRINT_FIELD(SYM) && symbol_conf.use_callchain)
+               else if (PRINT_FIELD(IP) && symbol_conf.use_callchain)
                        printf("%s ", thread->comm);
                else
                        printf("%16s ", thread->comm);
                print_trace_event(sample->cpu, sample->raw_data,
                                  sample->raw_size);
 
-       if (PRINT_FIELD(SYM)) {
+       if (PRINT_FIELD(IP)) {
                if (!symbol_conf.use_callchain)
                        printf(" ");
                else
                        printf("\n");
-               perf_session__print_symbols(event, sample, session);
+               perf_session__print_ip(event, sample, session,
+                                             PRINT_FIELD(SYM));
        }
 
        printf("\n");
        OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
                    "Look for files with symbols relative to this directory"),
        OPT_CALLBACK('f', "fields", NULL, "str",
-                    "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,sym",
+                    "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,ip,sym",
                     parse_output_fields),
 
        OPT_END()
 
        return NULL;
 }
 
-void perf_session__print_symbols(union perf_event *event,
-                               struct perf_sample *sample,
-                               struct perf_session *session)
+void perf_session__print_ip(union perf_event *event,
+                           struct perf_sample *sample,
+                           struct perf_session *session,
+                           int print_sym)
 {
        struct addr_location al;
        const char *symname, *dsoname;
                        if (!node)
                                break;
 
-                       if (node->sym && node->sym->name)
-                               symname = node->sym->name;
-                       else
-                               symname = "";
+                       printf("\t%16" PRIx64, node->ip);
+                       if (print_sym) {
+                               if (node->sym && node->sym->name)
+                                       symname = node->sym->name;
+                               else
+                                       symname = "";
 
-                       if (node->map && node->map->dso && node->map->dso->name)
-                               dsoname = node->map->dso->name;
-                       else
-                               dsoname = "";
+                               if (node->map && node->map->dso && node->map->dso->name)
+                                       dsoname = node->map->dso->name;
+                               else
+                                       dsoname = "";
 
-                       printf("\t%16" PRIx64 " %s (%s)\n", node->ip, symname, dsoname);
+                               printf(" %s (%s)", symname, dsoname);
+                       }
+                       printf("\n");
 
                        callchain_cursor_advance(cursor);
                }
 
        } else {
-               if (al.sym && al.sym->name)
-                       symname = al.sym->name;
-               else
-                       symname = "";
+               printf("%16" PRIx64, al.addr);
+               if (print_sym) {
+                       if (al.sym && al.sym->name)
+                               symname = al.sym->name;
+                       else
+                               symname = "";
 
-               if (al.map && al.map->dso && al.map->dso->name)
-                       dsoname = al.map->dso->name;
-               else
-                       dsoname = "";
+                       if (al.map && al.map->dso && al.map->dso->name)
+                               dsoname = al.map->dso->name;
+                       else
+                               dsoname = "";
 
-               printf("%16" PRIx64 " %s (%s)", al.addr, symname, dsoname);
+                       printf(" %s (%s)", symname, dsoname);
+               }
        }
 }
 
 struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
                                            unsigned int type);
 
-void perf_session__print_symbols(union perf_event *event,
+void perf_session__print_ip(union perf_event *event,
                                 struct perf_sample *sample,
-                                struct perf_session *session);
+                                struct perf_session *session,
+                                int print_sym);
 
 #endif /* __PERF_SESSION_H */