Fix: pass private data to context callbacks
[lttng-ust.git] / liblttng-ust / lttng-ust-statedump.c
CommitLineData
cf73e0fe 1/*
c0c0989a 2 * SPDX-License-Identifier: LGPL-2.1-or-later
cf73e0fe 3 *
c0c0989a
MJ
4 * Copyright (C) 2013 Paul Woegerer <paul_woegerer@mentor.com>
5 * Copyright (C) 2015 Antoine Busque <abusque@efficios.com>
6 * Copyright (C) 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
cf73e0fe
AB
7 */
8
1ddceb36 9#define _LGPL_SOURCE
8e2aed3f 10#include <link.h>
cf73e0fe 11#include <limits.h>
cf73e0fe 12#include <stdio.h>
8e2aed3f
AB
13#include <stdint.h>
14#include <stdlib.h>
97c7c238 15#include <stdbool.h>
8e2aed3f
AB
16#include <sys/types.h>
17#include <unistd.h>
cf73e0fe 18
2adb7ad2 19#include <ust-elf.h>
864a1eda 20#include <ust-helper.h>
cf73e0fe
AB
21#include "lttng-tracer-core.h"
22#include "lttng-ust-statedump.h"
97c7c238 23#include "jhash.h"
6f626d28 24#include "getenv.h"
94be38e8 25#include "compat.h"
7753d283 26#include "ust-events-internal.h"
cf73e0fe
AB
27
28#define TRACEPOINT_DEFINE
97c7c238
MD
29#include "ust_lib.h" /* Only define. */
30
cf73e0fe
AB
31#define TRACEPOINT_CREATE_PROBES
32#define TP_SESSION_CHECK
97c7c238 33#include "lttng-ust-statedump-provider.h" /* Define and create probes. */
cf73e0fe
AB
34
35struct dl_iterate_data {
cf73e0fe 36 int exec_found;
97c7c238
MD
37 bool first;
38 bool cancel;
cf73e0fe
AB
39};
40
f60e49df 41struct bin_info_data {
cf73e0fe 42 void *base_addr_ptr;
97c7c238 43 char resolved_path[PATH_MAX];
8e2aed3f
AB
44 char *dbg_file;
45 uint8_t *build_id;
46 uint64_t memsz;
47 size_t build_id_len;
cf73e0fe 48 int vdso;
8e2aed3f 49 uint32_t crc;
f5eb039d 50 uint8_t is_pic;
c5c4fd82
MD
51 uint8_t has_build_id;
52 uint8_t has_debug_link;
cf73e0fe
AB
53};
54
97c7c238
MD
55struct lttng_ust_dl_node {
56 struct bin_info_data bin_data;
57 struct cds_hlist_node node;
58 bool traced;
59 bool marked;
60};
61
62#define UST_DL_STATE_HASH_BITS 8
63#define UST_DL_STATE_TABLE_SIZE (1 << UST_DL_STATE_HASH_BITS)
64struct cds_hlist_head dl_state_table[UST_DL_STATE_TABLE_SIZE];
65
f69fe5fb 66typedef void (*tracepoint_cb)(struct lttng_ust_session *session, void *priv);
cf73e0fe 67
97c7c238
MD
68static
69struct lttng_ust_dl_node *alloc_dl_node(const struct bin_info_data *bin_data)
70{
71 struct lttng_ust_dl_node *e;
72
73 e = zmalloc(sizeof(struct lttng_ust_dl_node));
74 if (!e)
75 return NULL;
76 if (bin_data->dbg_file) {
77 e->bin_data.dbg_file = strdup(bin_data->dbg_file);
78 if (!e->bin_data.dbg_file)
79 goto error;
80 }
81 if (bin_data->build_id) {
82 e->bin_data.build_id = zmalloc(bin_data->build_id_len);
83 if (!e->bin_data.build_id)
84 goto error;
85 memcpy(e->bin_data.build_id, bin_data->build_id,
86 bin_data->build_id_len);
87 }
88 e->bin_data.base_addr_ptr = bin_data->base_addr_ptr;
89 memcpy(e->bin_data.resolved_path, bin_data->resolved_path, PATH_MAX);
90 e->bin_data.memsz = bin_data->memsz;
91 e->bin_data.build_id_len = bin_data->build_id_len;
92 e->bin_data.vdso = bin_data->vdso;
93 e->bin_data.crc = bin_data->crc;
94 e->bin_data.is_pic = bin_data->is_pic;
95 e->bin_data.has_build_id = bin_data->has_build_id;
96 e->bin_data.has_debug_link = bin_data->has_debug_link;
97 return e;
98
99error:
100 free(e->bin_data.build_id);
101 free(e->bin_data.dbg_file);
102 free(e);
103 return NULL;
104}
105
106static
107void free_dl_node(struct lttng_ust_dl_node *e)
108{
109 free(e->bin_data.build_id);
110 free(e->bin_data.dbg_file);
111 free(e);
112}
113
114/* Return 0 if same, nonzero if not. */
115static
116int compare_bin_data(const struct bin_info_data *a,
117 const struct bin_info_data *b)
118{
119 if (a->base_addr_ptr != b->base_addr_ptr)
120 return -1;
121 if (strcmp(a->resolved_path, b->resolved_path) != 0)
122 return -1;
123 if (a->dbg_file && !b->dbg_file)
124 return -1;
125 if (!a->dbg_file && b->dbg_file)
126 return -1;
127 if (a->dbg_file && strcmp(a->dbg_file, b->dbg_file) != 0)
128 return -1;
129 if (a->build_id && !b->build_id)
130 return -1;
131 if (!a->build_id && b->build_id)
132 return -1;
133 if (a->build_id_len != b->build_id_len)
134 return -1;
135 if (a->build_id &&
136 memcmp(a->build_id, b->build_id, a->build_id_len) != 0)
137 return -1;
138 if (a->memsz != b->memsz)
139 return -1;
140 if (a->vdso != b->vdso)
141 return -1;
142 if (a->crc != b->crc)
143 return -1;
144 if (a->is_pic != b->is_pic)
145 return -1;
146 if (a->has_build_id != b->has_build_id)
147 return -1;
148 if (a->has_debug_link != b->has_debug_link)
149 return -1;
150 return 0;
151}
152
153static
154struct lttng_ust_dl_node *find_or_create_dl_node(struct bin_info_data *bin_data)
155{
156 struct cds_hlist_head *head;
157 struct lttng_ust_dl_node *e;
158 unsigned int hash;
159 bool found = false;
160
161 hash = jhash(&bin_data->base_addr_ptr,
162 sizeof(bin_data->base_addr_ptr), 0);
163 head = &dl_state_table[hash & (UST_DL_STATE_TABLE_SIZE - 1)];
164 cds_hlist_for_each_entry_2(e, head, node) {
165 if (compare_bin_data(&e->bin_data, bin_data) != 0)
166 continue;
167 found = true;
168 break;
169 }
170 if (!found) {
171 /* Create */
172 e = alloc_dl_node(bin_data);
173 if (!e)
174 return NULL;
175 cds_hlist_add_head(&e->node, head);
176 }
177 return e;
178}
179
180static
181void remove_dl_node(struct lttng_ust_dl_node *e)
182{
183 cds_hlist_del(&e->node);
184}
185
cf73e0fe
AB
186/*
187 * Trace statedump event into all sessions owned by the caller thread
188 * for which statedump is pending.
189 */
190static
97c7c238 191void trace_statedump_event(tracepoint_cb tp_cb, void *owner, void *priv)
cf73e0fe
AB
192{
193 struct cds_list_head *sessionsp;
bdb12629 194 struct lttng_ust_session_private *session_priv;
cf73e0fe 195
7753d283 196 sessionsp = lttng_get_sessions();
bdb12629
MD
197 cds_list_for_each_entry(session_priv, sessionsp, node) {
198 if (session_priv->owner != owner)
cf73e0fe 199 continue;
bdb12629 200 if (!session_priv->statedump_pending)
cf73e0fe 201 continue;
bdb12629 202 tp_cb(session_priv->pub, priv);
cf73e0fe 203 }
cf73e0fe
AB
204}
205
206static
f69fe5fb 207void trace_bin_info_cb(struct lttng_ust_session *session, void *priv)
cf73e0fe 208{
f60e49df 209 struct bin_info_data *bin_data = (struct bin_info_data *) priv;
cf73e0fe 210
f60e49df
AB
211 tracepoint(lttng_ust_statedump, bin_info,
212 session, bin_data->base_addr_ptr,
c5c4fd82
MD
213 bin_data->resolved_path, bin_data->memsz,
214 bin_data->is_pic, bin_data->has_build_id,
215 bin_data->has_debug_link);
8e2aed3f
AB
216}
217
218static
f69fe5fb 219void trace_build_id_cb(struct lttng_ust_session *session, void *priv)
8e2aed3f 220{
f60e49df 221 struct bin_info_data *bin_data = (struct bin_info_data *) priv;
8e2aed3f
AB
222
223 tracepoint(lttng_ust_statedump, build_id,
f60e49df
AB
224 session, bin_data->base_addr_ptr,
225 bin_data->build_id, bin_data->build_id_len);
8e2aed3f
AB
226}
227
228static
f69fe5fb 229void trace_debug_link_cb(struct lttng_ust_session *session, void *priv)
8e2aed3f 230{
f60e49df 231 struct bin_info_data *bin_data = (struct bin_info_data *) priv;
8e2aed3f
AB
232
233 tracepoint(lttng_ust_statedump, debug_link,
f60e49df
AB
234 session, bin_data->base_addr_ptr,
235 bin_data->dbg_file, bin_data->crc);
cf73e0fe
AB
236}
237
94be38e8 238static
f69fe5fb 239void procname_cb(struct lttng_ust_session *session, void *priv)
94be38e8
JR
240{
241 char *procname = (char *) priv;
242 tracepoint(lttng_ust_statedump, procname, session, procname);
243}
244
cf73e0fe 245static
2208d8b5 246void trace_start_cb(struct lttng_ust_session *session, void *priv __attribute__((unused)))
cf73e0fe
AB
247{
248 tracepoint(lttng_ust_statedump, start, session);
249}
250
251static
2208d8b5 252void trace_end_cb(struct lttng_ust_session *session, void *priv __attribute__((unused)))
cf73e0fe
AB
253{
254 tracepoint(lttng_ust_statedump, end, session);
255}
256
8e2aed3f 257static
c5c4fd82
MD
258int get_elf_info(struct bin_info_data *bin_data)
259{
8e2aed3f 260 struct lttng_ust_elf *elf;
c5c4fd82 261 int ret = 0, found;
8e2aed3f 262
f60e49df 263 elf = lttng_ust_elf_create(bin_data->resolved_path);
8e2aed3f
AB
264 if (!elf) {
265 ret = -1;
266 goto end;
267 }
268
f60e49df 269 ret = lttng_ust_elf_get_memsz(elf, &bin_data->memsz);
8e2aed3f
AB
270 if (ret) {
271 goto end;
272 }
273
c5c4fd82 274 found = 0;
f60e49df 275 ret = lttng_ust_elf_get_build_id(elf, &bin_data->build_id,
c5c4fd82
MD
276 &bin_data->build_id_len,
277 &found);
8e2aed3f
AB
278 if (ret) {
279 goto end;
280 }
c5c4fd82
MD
281 bin_data->has_build_id = !!found;
282 found = 0;
f60e49df 283 ret = lttng_ust_elf_get_debug_link(elf, &bin_data->dbg_file,
c5c4fd82
MD
284 &bin_data->crc,
285 &found);
8e2aed3f
AB
286 if (ret) {
287 goto end;
288 }
c5c4fd82 289 bin_data->has_debug_link = !!found;
8e2aed3f 290
f60e49df 291 bin_data->is_pic = lttng_ust_elf_is_pic(elf);
f5eb039d 292
8e2aed3f
AB
293end:
294 lttng_ust_elf_destroy(elf);
295 return ret;
296}
297
cf73e0fe 298static
97c7c238
MD
299void trace_baddr(struct bin_info_data *bin_data, void *owner)
300{
301 trace_statedump_event(trace_bin_info_cb, owner, bin_data);
302
303 if (bin_data->has_build_id)
304 trace_statedump_event(trace_build_id_cb, owner, bin_data);
305
306 if (bin_data->has_debug_link)
307 trace_statedump_event(trace_debug_link_cb, owner, bin_data);
308}
309
310static
311int extract_baddr(struct bin_info_data *bin_data)
cf73e0fe 312{
c5c4fd82 313 int ret = 0;
97c7c238 314 struct lttng_ust_dl_node *e;
8e2aed3f 315
f60e49df 316 if (!bin_data->vdso) {
c5c4fd82 317 ret = get_elf_info(bin_data);
8e2aed3f
AB
318 if (ret) {
319 goto end;
320 }
321 } else {
f60e49df 322 bin_data->memsz = 0;
fd783031
MD
323 bin_data->has_build_id = 0;
324 bin_data->has_debug_link = 0;
8e2aed3f
AB
325 }
326
97c7c238
MD
327 e = find_or_create_dl_node(bin_data);
328 if (!e) {
329 ret = -1;
8e2aed3f
AB
330 goto end;
331 }
97c7c238 332 e->marked = true;
8e2aed3f 333end:
97c7c238
MD
334 free(bin_data->build_id);
335 bin_data->build_id = NULL;
336 free(bin_data->dbg_file);
337 bin_data->dbg_file = NULL;
8e2aed3f 338 return ret;
cf73e0fe
AB
339}
340
341static
97c7c238 342void trace_statedump_start(void *owner)
cf73e0fe 343{
97c7c238 344 trace_statedump_event(trace_start_cb, owner, NULL);
cf73e0fe
AB
345}
346
347static
97c7c238 348void trace_statedump_end(void *owner)
cf73e0fe 349{
97c7c238 350 trace_statedump_event(trace_end_cb, owner, NULL);
cf73e0fe
AB
351}
352
353static
97c7c238 354void iter_begin(struct dl_iterate_data *data)
cf73e0fe 355{
97c7c238 356 unsigned int i;
cf73e0fe 357
d34e6761
MD
358 /*
359 * UST lock nests within dynamic loader lock.
360 *
97c7c238 361 * Hold this lock across handling of the module listing to
d34e6761
MD
362 * protect memory allocation at early process start, due to
363 * interactions with libc-wrapper lttng malloc instrumentation.
364 */
365 if (ust_lock()) {
97c7c238
MD
366 data->cancel = true;
367 return;
d34e6761
MD
368 }
369
97c7c238
MD
370 /* Ensure all entries are unmarked. */
371 for (i = 0; i < UST_DL_STATE_TABLE_SIZE; i++) {
372 struct cds_hlist_head *head;
373 struct lttng_ust_dl_node *e;
374
375 head = &dl_state_table[i];
376 cds_hlist_for_each_entry_2(e, head, node)
377 assert(!e->marked);
378 }
379}
380
381static
382void trace_lib_load(const struct bin_info_data *bin_data, void *ip)
383{
384 tracepoint(lttng_ust_lib, load,
385 ip, bin_data->base_addr_ptr, bin_data->resolved_path,
386 bin_data->memsz, bin_data->has_build_id,
387 bin_data->has_debug_link);
388
389 if (bin_data->has_build_id) {
390 tracepoint(lttng_ust_lib, build_id,
391 ip, bin_data->base_addr_ptr, bin_data->build_id,
392 bin_data->build_id_len);
393 }
394
395 if (bin_data->has_debug_link) {
396 tracepoint(lttng_ust_lib, debug_link,
397 ip, bin_data->base_addr_ptr, bin_data->dbg_file,
398 bin_data->crc);
399 }
400}
401
402static
403void trace_lib_unload(const struct bin_info_data *bin_data, void *ip)
404{
405 tracepoint(lttng_ust_lib, unload, ip, bin_data->base_addr_ptr);
406}
407
408static
409void iter_end(struct dl_iterate_data *data, void *ip)
410{
411 unsigned int i;
412
2eb235ec
MD
413 if (data->cancel)
414 goto end;
97c7c238
MD
415 /*
416 * Iterate on hash table.
417 * For each marked, traced, do nothing.
418 * For each marked, not traced, trace lib open event. traced = true.
419 * For each unmarked, traced, trace lib close event. remove node.
420 * For each unmarked, not traced, remove node.
421 */
422 for (i = 0; i < UST_DL_STATE_TABLE_SIZE; i++) {
423 struct cds_hlist_head *head;
424 struct lttng_ust_dl_node *e;
425
426 head = &dl_state_table[i];
427 cds_hlist_for_each_entry_2(e, head, node) {
428 if (e->marked) {
429 if (!e->traced) {
430 trace_lib_load(&e->bin_data, ip);
431 e->traced = true;
432 }
b891574e 433 e->marked = false;
97c7c238
MD
434 } else {
435 if (e->traced)
436 trace_lib_unload(&e->bin_data, ip);
437 remove_dl_node(e);
438 free_dl_node(e);
439 }
97c7c238
MD
440 }
441 }
2eb235ec 442end:
97c7c238
MD
443 ust_unlock();
444}
445
446static
2208d8b5 447int extract_bin_info_events(struct dl_phdr_info *info, size_t size __attribute__((unused)), void *_data)
97c7c238
MD
448{
449 int j, ret = 0;
450 struct dl_iterate_data *data = _data;
451
452 if (data->first) {
453 iter_begin(data);
454 data->first = false;
455 }
456
457 if (data->cancel)
458 goto end;
459
cf73e0fe 460 for (j = 0; j < info->dlpi_phnum; j++) {
f60e49df 461 struct bin_info_data bin_data;
cf73e0fe
AB
462
463 if (info->dlpi_phdr[j].p_type != PT_LOAD)
464 continue;
465
97c7c238
MD
466 memset(&bin_data, 0, sizeof(bin_data));
467
cf73e0fe 468 /* Calculate virtual memory address of the loadable segment */
97c7c238 469 bin_data.base_addr_ptr = (void *) info->dlpi_addr +
cf73e0fe
AB
470 info->dlpi_phdr[j].p_vaddr;
471
472 if ((info->dlpi_name == NULL || info->dlpi_name[0] == 0)) {
473 /*
474 * Only the first phdr without a dlpi_name
475 * encountered is considered as the program
476 * executable. The rest are vdsos.
477 */
478 if (!data->exec_found) {
479 ssize_t path_len;
480 data->exec_found = 1;
481
482 /*
483 * Use /proc/self/exe to resolve the
484 * executable's full path.
485 */
486 path_len = readlink("/proc/self/exe",
97c7c238 487 bin_data.resolved_path,
cf73e0fe
AB
488 PATH_MAX - 1);
489 if (path_len <= 0)
490 break;
491
97c7c238 492 bin_data.resolved_path[path_len] = '\0';
f60e49df 493 bin_data.vdso = 0;
cf73e0fe 494 } else {
97c7c238
MD
495 snprintf(bin_data.resolved_path,
496 PATH_MAX - 1, "[vdso]");
f60e49df 497 bin_data.vdso = 1;
cf73e0fe
AB
498 }
499 } else {
500 /*
501 * For regular dl_phdr_info entries check if
f60e49df 502 * the path to the binary really exists. If not,
cf73e0fe
AB
503 * treat as vdso and use dlpi_name as 'path'.
504 */
97c7c238
MD
505 if (!realpath(info->dlpi_name,
506 bin_data.resolved_path)) {
507 snprintf(bin_data.resolved_path,
508 PATH_MAX - 1, "[%s]",
cf73e0fe 509 info->dlpi_name);
f60e49df 510 bin_data.vdso = 1;
89be5359 511 } else {
f60e49df 512 bin_data.vdso = 0;
cf73e0fe
AB
513 }
514 }
515
97c7c238 516 ret = extract_baddr(&bin_data);
d34e6761 517 break;
cf73e0fe 518 }
d34e6761 519end:
d34e6761 520 return ret;
cf73e0fe
AB
521}
522
cf73e0fe 523static
97c7c238
MD
524void ust_dl_table_statedump(void *owner)
525{
526 unsigned int i;
527
528 if (ust_lock())
529 goto end;
530
531 /* Statedump each traced table entry into session for owner. */
532 for (i = 0; i < UST_DL_STATE_TABLE_SIZE; i++) {
533 struct cds_hlist_head *head;
534 struct lttng_ust_dl_node *e;
535
536 head = &dl_state_table[i];
537 cds_hlist_for_each_entry_2(e, head, node) {
538 if (e->traced)
539 trace_baddr(&e->bin_data, owner);
540 }
541 }
542
543end:
544 ust_unlock();
545}
546
547void lttng_ust_dl_update(void *ip)
cf73e0fe
AB
548{
549 struct dl_iterate_data data;
550
4c41b460 551 if (lttng_ust_getenv("LTTNG_UST_WITHOUT_BADDR_STATEDUMP"))
97c7c238 552 return;
cf73e0fe 553
c362addf
MD
554 /*
555 * Fixup lttng-ust TLS when called from dlopen/dlclose
556 * instrumentation.
557 */
558 lttng_ust_fixup_tls();
559
cf73e0fe 560 data.exec_found = 0;
97c7c238
MD
561 data.first = true;
562 data.cancel = false;
cf73e0fe
AB
563 /*
564 * Iterate through the list of currently loaded shared objects and
97c7c238 565 * generate tables entries for loadable segments using
f60e49df 566 * extract_bin_info_events.
97c7c238
MD
567 * Removed libraries are detected by mark-and-sweep: marking is
568 * done in the iteration over libraries, and sweeping is
569 * performed by iter_end().
cf73e0fe 570 */
f60e49df 571 dl_iterate_phdr(extract_bin_info_events, &data);
97c7c238
MD
572 if (data.first)
573 iter_begin(&data);
574 iter_end(&data, ip);
575}
cf73e0fe 576
97c7c238
MD
577/*
578 * Generate a statedump of base addresses of all shared objects loaded
579 * by the traced application, as well as for the application's
580 * executable itself.
581 */
582static
583int do_baddr_statedump(void *owner)
584{
4c41b460 585 if (lttng_ust_getenv("LTTNG_UST_WITHOUT_BADDR_STATEDUMP"))
97c7c238
MD
586 return 0;
587 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
588 ust_dl_table_statedump(owner);
cf73e0fe
AB
589 return 0;
590}
591
94be38e8
JR
592static
593int do_procname_statedump(void *owner)
594{
4c41b460 595 if (lttng_ust_getenv("LTTNG_UST_WITHOUT_PROCNAME_STATEDUMP"))
94be38e8
JR
596 return 0;
597
598 trace_statedump_event(procname_cb, owner, lttng_ust_sockinfo_get_procname(owner));
599 return 0;
600}
601
cf73e0fe
AB
602/*
603 * Generate a statedump of a given traced application. A statedump is
604 * delimited by start and end events. For a given (process, session)
605 * pair, begin/end events are serialized and will match. However, in a
606 * session, statedumps from different processes may be
607 * interleaved. The vpid context should be used to identify which
608 * events belong to which process.
8002ea62
MD
609 *
610 * Grab the ust_lock outside of the RCU read-side lock because we
611 * perform synchronize_rcu with the ust_lock held, which can trigger
612 * deadlocks otherwise.
cf73e0fe
AB
613 */
614int do_lttng_ust_statedump(void *owner)
615{
8002ea62 616 ust_lock_nocheck();
cf73e0fe 617 trace_statedump_start(owner);
8002ea62
MD
618 ust_unlock();
619
94be38e8 620 do_procname_statedump(owner);
cf73e0fe 621 do_baddr_statedump(owner);
8002ea62
MD
622
623 ust_lock_nocheck();
cf73e0fe 624 trace_statedump_end(owner);
8002ea62 625 ust_unlock();
cf73e0fe
AB
626
627 return 0;
628}
629
630void lttng_ust_statedump_init(void)
631{
632 __tracepoints__init();
633 __tracepoints__ptrs_init();
634 __lttng_events_init__lttng_ust_statedump();
97c7c238
MD
635 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
636}
637
638static
639void ust_dl_state_destroy(void)
640{
641 unsigned int i;
642
643 for (i = 0; i < UST_DL_STATE_TABLE_SIZE; i++) {
644 struct cds_hlist_head *head;
645 struct lttng_ust_dl_node *e, *tmp;
646
647 head = &dl_state_table[i];
648 cds_hlist_for_each_entry_safe_2(e, tmp, head, node)
649 free_dl_node(e);
650 CDS_INIT_HLIST_HEAD(head);
651 }
cf73e0fe
AB
652}
653
654void lttng_ust_statedump_destroy(void)
655{
656 __lttng_events_exit__lttng_ust_statedump();
657 __tracepoints__ptrs_destroy();
658 __tracepoints__destroy();
97c7c238 659 ust_dl_state_destroy();
cf73e0fe 660}
This page took 0.059513 seconds and 4 git commands to generate.