return 0;
 }
 
+static int field_is_relative_dynamic(struct tep_format_field *field)
+{
+       if (strncmp(field->type, "__rel_loc", 9) == 0)
+               return 1;
+
+       return 0;
+}
+
 static int field_is_long(struct tep_format_field *field)
 {
        /* includes long long */
                        field->flags |= TEP_FIELD_IS_STRING;
                if (field_is_dynamic(field))
                        field->flags |= TEP_FIELD_IS_DYNAMIC;
+               if (field_is_relative_dynamic(field))
+                       field->flags |= TEP_FIELD_IS_DYNAMIC | TEP_FIELD_IS_RELATIVE;
                if (field_is_long(field))
                        field->flags |= TEP_FIELD_IS_LONG;
 
 
        arg->type = TEP_PRINT_STRING;
        arg->string.string = token;
-       arg->string.offset = -1;
+       arg->string.field = NULL;
 
        if (read_expected(TEP_EVENT_DELIM, ")") < 0)
                goto out_err;
 
        arg->type = TEP_PRINT_BITMASK;
        arg->bitmask.bitmask = token;
-       arg->bitmask.offset = -1;
+       arg->bitmask.field = NULL;
 
        if (read_expected(TEP_EVENT_DELIM, ")") < 0)
                goto out_err;
                free_token(token);
                return process_int_array(event, arg, tok);
        }
-       if (strcmp(token, "__get_str") == 0) {
+       if (strcmp(token, "__get_str") == 0 ||
+           strcmp(token, "__get_rel_str") == 0) {
                free_token(token);
                return process_str(event, arg, tok);
        }
-       if (strcmp(token, "__get_bitmask") == 0) {
+       if (strcmp(token, "__get_bitmask") == 0 ||
+           strcmp(token, "__get_rel_bitmask") == 0) {
                free_token(token);
                return process_bitmask(event, arg, tok);
        }
-       if (strcmp(token, "__get_dynamic_array") == 0) {
+       if (strcmp(token, "__get_dynamic_array") == 0 ||
+           strcmp(token, "__get_rel_dynamic_array") == 0) {
                free_token(token);
                return process_dynamic_array(event, arg, tok);
        }
-       if (strcmp(token, "__get_dynamic_array_len") == 0) {
+       if (strcmp(token, "__get_dynamic_array_len") == 0 ||
+           strcmp(token, "__get_rel_dynamic_array_len") == 0) {
                free_token(token);
                return process_dynamic_array_len(event, arg, tok);
        }
        case TEP_PRINT_STRING: {
                int str_offset;
 
-               if (arg->string.offset == -1) {
-                       struct tep_format_field *f;
+               if (!arg->string.field)
+                       arg->string.field = tep_find_any_field(event, arg->string.string);
+               if (!arg->string.field)
+                       break;
 
-                       f = tep_find_any_field(event, arg->string.string);
-                       arg->string.offset = f->offset;
-               }
-               str_offset = data2host4(tep, *(unsigned int *)(data + arg->string.offset));
+               str_offset = data2host4(tep,
+                               *(unsigned int *)(data + arg->string.field->offset));
                str_offset &= 0xffff;
+               if (arg->string.field->flags & TEP_FIELD_IS_RELATIVE)
+                       str_offset += arg->string.field->offset + arg->string.field->size;
                print_str_to_seq(s, format, len_arg, ((char *)data) + str_offset);
                break;
        }
                int bitmask_offset;
                int bitmask_size;
 
-               if (arg->bitmask.offset == -1) {
-                       struct tep_format_field *f;
-
-                       f = tep_find_any_field(event, arg->bitmask.bitmask);
-                       arg->bitmask.offset = f->offset;
-               }
-               bitmask_offset = data2host4(tep, *(unsigned int *)(data + arg->bitmask.offset));
+               if (!arg->bitmask.field)
+                       arg->bitmask.field = tep_find_any_field(event, arg->bitmask.bitmask);
+               if (!arg->bitmask.field)
+                       break;
+               bitmask_offset = data2host4(tep,
+                               *(unsigned int *)(data + arg->bitmask.field->offset));
                bitmask_size = bitmask_offset >> 16;
                bitmask_offset &= 0xffff;
+               if (arg->bitmask.field->flags & TEP_FIELD_IS_RELATIVE)
+                       bitmask_offset += arg->bitmask.field->offset + arg->bitmask.field->size;
                print_bitmask_to_seq(tep, s, format, len_arg,
                                     data + bitmask_offset, bitmask_size);
                break;
                        offset = val;
                        len = offset >> 16;
                        offset &= 0xffff;
+                       if (field->flags & TEP_FIELD_IS_RELATIVE)
+                               offset += field->offset + field->size;
                }
                if (field->flags & TEP_FIELD_IS_STRING &&
                    is_printable_array(data + offset, len)) {
                                         data + offset, field->size);
                *len = offset >> 16;
                offset &= 0xffff;
+               if (field->flags & TEP_FIELD_IS_RELATIVE)
+                       offset += field->offset + field->size;
        } else
                *len = field->size;